zoukankan      html  css  js  c++  java
  • 2018 8.8 提高A组模拟赛

    T1
    Description

    被污染的灰灰草原上有羊和狼。有N只动物围成一圈,每只动物是羊或狼。
    该游戏从其中的一只动物开始,报出[1,K]区间的整数,若上一只动物报出的数是x,下一只动物可以报[x+1,x+K]区间的整数,游戏按顺时针方向进行。每只动物报的数字都不能超过M。若一只动物报了M这个数,它所在的种族就输了。问以第i只动物为游戏的开始,最后哪种动物会赢?

    Input

    第一行输入三个正整数N,M,K。
    接下来一行N个正整数,分别表示N只动物的种类,以顺时针的方向给出。0代表羊,1代表狼。

    Output

    一行输出N个整数,表示若从第i只动物开始,赢的动物的种类。同上,0代表羊,1代表狼。

    Sample Input

    Input 1
    2 9 2
    0 1
    Input 2
    6 499 5
    1 0 0 1 1 0
    Input 3
    10 100 10
    0 0 0 1 1 1 1 0 1 1

    Sample Output

    Output 1
    0 1
    Output 2
    0 1 1 1 1 0
    Output 3
    1 1 1 1 1 1 1 1 1 1

    Data Constraint

    对于60%的数据,1 ≤ N, M, K ≤ 500。
    对于100%的数据,1 ≤ N, M, K ≤ 5000。

    解题思路

    dp+博弈论,dp[i][j]表示 轮i报数报到j有无必胜策略,这样是n^3的,需要前缀和优化,如果前缀和=0,说明此时状态为必败。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    
    using namespace std;
    const int MAXN = 5005;
    
    int dp[MAXN<<1][MAXN];
    int n,m,K,sum,a[MAXN];
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    inline int pre(int x){
        return x%n==0?n:x%n; 
    }
    
    int main(){
        freopen("vode.in","r",stdin);
        freopen("vode.out","w",stdout);
        n=rd();m=rd();K=rd();
        for(register int i=1;i<=n;i++) a[i]=rd();
    //  for(register int i=1;i<=n+m;i++) 
    //      for(register int j=1;j<=m;j++) dp[i][j]=1;
    //  for(register int i=1;i<=n+m;i++) dp[i][m]=0;
        for(register int i=n+m-1;i;i--){
            sum=0;
            for(register int j=m-1;j;j--){
                if(a[pre(i)]==a[pre(i+1)]) dp[i][j]=(sum>0);
                else dp[i][j]=(sum==0);
                sum+=dp[i+1][j];
                if(j+K<=m) sum-=dp[i+1][j+K]; 
            }
        }
        for(register int i=1;i<=n;i++){
            int flag=0;
            for(register int j=1;j<=K;j++)
                if(dp[i][j]) {flag=1;break;}
            printf("%d ",flag?a[i]:a[i]^1);
        }
        return 0;
    }

    T2
    Description

    有一副n*m的地图,有n*m块地,每块是下列四种中的一种:
    墙:用#表示,墙有4个面,分别是前面,后面,左面,右面。
    起点:用C表示,为主角的起点,是一片空地。
    终点:用F表示,为主角的目的地,是一片空地。
    空地:用 . 表示。
    其中除了墙不能穿过,其他地方都能走。

    主角有以下3种操作:
    1.移动到相邻的前后左右的地方,花费一个单位时间。
    2.向前后左右其中一个方向发射子弹,子弹沿直线穿过,打在最近的一堵墙的一面,然后墙的这面就会形成一个开口通往秘密通道。同一时间最多只能有两个开口,若出现有3个开口,出现时间最早的开口会立即消失。该操作不用时间。
    3.可以从一个与开口相邻的空地跳进去,进入秘密通道,从另外一个开口正对的空地跳出来。这个过程花费一个单位时间。

    地图四周都是墙,问主角最少用多少时间从C走到F。C和F
    只会出现一次。

    Input

    第一行输入两个正整数n,m。
    接下来n行,每行m个字符描述地图。

    Output

    输出1个整数,表示最短时间完成路途。如果无解输出nemoguce

    Sample Input

    Input 1
    4 4

    #

    .F

    C.

    #

    Input 2
    6 8

    #

    .##..F

    C.##..

    ..#…

    …..

    #

    Input 3
    4 5

    #

    C#.

    F

    #

    Sample Output

    Output 1
    2
    Output 2
    4
    Output 3
    nemoguce

    Data Constraint

    对于50%的数据,4≤ n,m≤ 15。
    对于100%的数据,4≤ n,m≤ 500。

    Hint

    总共用到8次操作,时间之和为4。如下图所示
    1.向左射一枪,在(3,1)的右面出现开口。
    2.向下射一枪,在(6,2)的上面出现开口。
    3.向左从(3,1)进入秘密通道,从(6,2)中出来,到达(5,2)。用1单位时间。
    4.向右射一枪,在(5,7)的左面出现开口,(3,1)右面的开口消失。
    5.走进(6,2)的开口,出来到(5,6)。用1单位时间。
    6.向上射一枪,在(1,6)的下面出现开口。
    7.经过秘密通道,走到(2,6)。用1单位时间。
    8.走到终点。用1单位时间。

    解题思路

    对于每个非墙的点,向它四周连一条边权为1的边,还要向它四周的墙连一条据他最近的墙的边,然后跑一边最短路即为答案。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    
    using namespace std;
    const int MAXN = 502;
    const int MAXM = MAXN*MAXN;
    const int inf = 0x3f3f3f3f;
    
    int n,m,head[MAXM],cnt,S,T,dis[MAXM];
    int to[MAXM<<3],nxt[MAXM<<3],val[MAXM<<3];
    char c[MAXN][MAXN];
    bool vis[MAXM];
    queue<int> Q;
    
    inline void add(int bg,int ed,int w){
        to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt,val[cnt]=w;
    }
    
    inline void spfa(){
        memset(dis,0x3f,sizeof(dis));
        dis[S]=0;vis[S]=1;Q.push(S);
        while(!Q.empty()){
            int x=Q.front();Q.pop();vis[x]=0;
            for(register int i=head[x];i;i=nxt[i]){
                int u=to[i];
                if(dis[x]+val[i]<dis[u]){
                    dis[u]=dis[x]+val[i];
                    if(!vis[u]){
                        vis[u]=1;
                        Q.push(u);
                    }
                }
            }
        }
    }
    
    inline int minn(int x,int y){
        if(x>y) return y;
        return x;
    }
    
    int main(){
        freopen("portal.in","r",stdin);
        freopen("portal.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(register int i=1;i<=n;i++) scanf("%s",c[i]+1);
        for(register int i=2;i<n;i++)
            for(register int j=2;j<m;j++){
                if(c[i][j]=='C') S=(i-1)*m+j;
                if(c[i][j]=='F') T=(i-1)*m+j;
                if(c[i][j]!='#') {
                    if(c[i+1][j]!='#') add((i-1)*m+j,i*m+j,1),add(i*m+j,(i-1)*m+j,1);
                    if(c[i][j+1]!='#') add((i-1)*m+j,(i-1)*m+j+1,1),add((i-1)*m+j+1,(i-1)*m+j,1);
                }
            }
        for(register int i=2;i<n;i++)
        for(register int j=2;j<m;j++) if(c[i][j]!='#') {
                int u,d,l,r;int zz=(i-1)*m;
                int xx=i,yy=j;int w=1e9;
                while(c[xx][yy+1]!='#') yy++;
                w=minn(w,yy-j);u=yy;yy=j;
                while(c[xx][yy-1]!='#') yy--;
                w=minn(w,j-yy);d=yy;yy=j;
                while(c[xx+1][yy]!='#') xx++;
                w=minn(w,xx-i);r=xx;xx=i;
                while(c[xx-1][yy]!='#') xx--;
                w=minn(w,i-xx);l=xx;xx=i;w++;
                if(u!=yy) add(zz+j,zz+u,w);
                if(d!=yy) add(zz+j,zz+d,w);
                if(r!=xx) add(zz+j,(r-1)*m+j,w);
                if(l!=xx) add(zz+j,(l-1)*m+j,w);
            }
        spfa();
        if(dis[T]!=inf) printf("%d",dis[T]);
        else puts("nemoguce");
    }

    T3

    Input

    第一行输入三个正整数n,m,q,其中q表示询问个数。
    接下来q行,每行两个正整数x,y,表示询问城市x和城市y最早什么时候连通。

    Output

    输出q行,每行一个正整数,表示最早连通的天数

    Sample Input

    Input 1
    8 3 3
    2 5
    3 6
    4 8
    Input 2
    25 6 1
    20 9
    Input 3
    9999 2222 2
    1025 2405
    3154 8949

    Sample Output

    Output 1
    3
    1
    2
    Output 2
    4
    Output 3
    1980
    2160

    Data Constraint

    对于40%的数据,n≤ 1000,q<=100000
    对于100%的数据,1 ≤ n,q≤ 100000,1<=m<=q

    解题思路

    发现每天所连的边为调和级数,不超过nln n 级别的,而树高不超过log n。所以用按秩合并的权值并查集合并,然后每次暴力求lca,在两个点的链上求最小值。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<set>
    
    using namespace std;
    const int MAXN = 100005;
    
    int n,m,q,siz[MAXN],val[MAXN];
    int fa[MAXN],ans;
    set<int> S;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    inline int fd(int x){
        if(x==fa[x]) return x;
        return fd(fa[x]);
    }
    
    inline void update(int x,int y,int t){
        int u=fd(x),v=fd(y);
        if(u==v) return;
        if(siz[u]>siz[v]){
            val[v]=t;fa[v]=u;
            siz[u]+=siz[v];
        }
        else{
            val[u]=t;fa[u]=v;
            siz[v]+=siz[u];
        }
    }
    
    int main(){
        freopen("pictionary.in","r",stdin);
        freopen("pictionary.out","w",stdout);
        n=rd();m=rd();q=rd();
        for(register int i=1;i<=n;i++) fa[i]=i,siz[i]=1;
        for(register int i=1;i<=m;i++){
            int now=m-i+1;
            for(register int j=now*2;j<=n;j+=now) update(now,j,i);
        }
        for(register int i=1;i<=q;i++){
            int x=rd(),y=rd();int xx=x;
            ans=0;S.clear();
            while(x!=fa[x]) S.insert(x),x=fa[x];
            while(y!=fa[y] && S.find(y)==S.end()) ans=max(ans,val[y]),y=fa[y];
            while(xx!=y) ans=max(ans,val[xx]),xx=fa[xx];
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    HDU 5302(Connect the Graph- 构造)
    Redis 集群
    HDFS集中式缓存管理(Centralized Cache Management)
    JavaScript语言基础12
    【IOS】启动画面
    小贝_mysql优化学习
    hdu2099 整除的位数(暴力)
    Receiver type ‘X’ for instance message is a forward declaration
    动态游标(比如表名作为參数)以及动态SQL分析
    mongodb与SQL相应关系表
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676898.html
Copyright © 2011-2022 走看看