zoukankan      html  css  js  c++  java
  • 10.14模拟总结

    今天模拟很有趣,你只要写一份AC代码就能顺便用它来与好友进行k子棋和围棋的混合棋(只是不支持悔棋)。

    T1.FIR

    期望得分100,实际得分64,(如果有subtask是0分)

    这就是那道有趣的题。大模拟……

    判断赢我的办法是dfs,分别向八个方向搜索,把相对应的两个方向的答案加上看是否有一个符合。

    判断死的话,从一个子开始bfs,遇到同颜色子压入队列,如果周围有一口气就能活,如果搜到最后也没有的话就是死了。

    判断吃子的话,找这个子四周的子,遇到一个不同颜色的就开始判死,如果死了的话,我们把棋盘那个位置还原。(我的办法是开一个栈记录一下搜到了哪些子)

    判断的顺序是:先不合法(那个位置有棋),再判吃子,再判胜利,如果吃不了子判死亡,没死判胜利。

    然后本人因为打了vis标记然后……没用,凉凉。而且还忘了一次能吃好几个子,又凉凉。注意棋盘是无限的,所以其实在边上的子是有气的,而且你还杀不死它。

    改完之后就好了,同时也看一下std,非常简洁……只用了我一半的码长……

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<utility>
    #include<map>
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    using namespace std;
    typedef long long ll;
    const int M = 100005;
    const int N = 10000005;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >='0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    
    struct node
    {
        int x,y;
    };
    
    int n,p,g[1005][1005],stack[1005][3],top,x,y;
    int dx[10] = {0,1,1,0,-1,-1,-1,0,1},dy[10] = {0,0,1,1,1,0,-1,-1,-1};
    int sx[6] = {0,1,0,-1,0},sy[6] = {0,0,1,0,-1};
    
    bool vis[1005][1005];
    queue <node> q;
    
    bool pddie(int x,int y,bool f)
    {
        bool flag = 0;
        if(x == 3 && y == 4) flag = 1;
        while(!q.empty()) q.pop();
        q.push((node){x,y});
        while(!q.empty())
        {
            node k = q.front();
            q.pop();
    //        if(flag) printf("%d %d
    ",k.x,k.y);
            vis[k.x][k.y] = 1,stack[++top][0] = k.x,stack[top][1] = k.y;
            rep(i,1,4)
            {
                int kx = k.x + sx[i],ky = k.y + sy[i];
                if(vis[kx][ky]) continue;
                //if(kx < 1 || ky < 1) continue;
                if(g[kx][ky] == -1)
                {
                    while(top) vis[stack[top][0]][stack[top][1]] = 0,top--;
                    return 0;
                }
                else if(g[kx][ky] == f) q.push((node){kx,ky});
            }
        }
        return 1;
    }
    
    bool pduse(int x,int y)
    {
        return g[x][y] != -1;
    }
    
    bool pdeat(int x,int y,bool f)
    {
        bool fla = 0;
        g[x][y] = f;
        rep(i,1,4)
        {
            int kx = x + sx[i],ky = y + sy[i];
            if(kx < 1 || ky < 1) continue;
            if(g[kx][ky] == (f^1))
            {
    //            printf("!%d %d
    ",kx,ky);
                if(pddie(kx,ky,f^1))
                {
    //                printf("@
    ");
                    while(top)
                    {
                        vis[stack[top][0]][stack[top][1]] = 0;
                        g[stack[top][0]][stack[top][1]] = -1,top--;
                    }
                    fla = 1;
                }
            }
        }
        g[x][y] = -1;
        return fla;
    }
    
    int dfs(int x,int y,int dir,bool f)
    {
        if(g[x][y] != f) return 0;
        else if(x < 1 || y < 1) return 0;
        else return dfs(x + dx[dir],y + dy[dir],dir,f) + 1;
    }
    
    bool pdwin(int x,int y,bool f)
    {
        if(dfs(x,y,1,f) + dfs(x,y,5,f) - 1 >= p) return 1;
        if(dfs(x,y,2,f) + dfs(x,y,6,f) - 1 >= p) return 1;
        if(dfs(x,y,3,f) + dfs(x,y,7,f) - 1 >= p) return 1;
        if(dfs(x,y,4,f) + dfs(x,y,8,f) - 1 >= p) return 1;
        return 0;
    }
    
    void printgraph()
    {
        rep(l,1,10)
        {
            rep(j,1,10)
            {
                if(g[l][j] == 1) putchar('O');
                else if(g[l][j] == 0) putchar('X');
                else putchar('.');
            }
            enter;
        }
    }
    
    int main()
    {
        freopen("fir.in","r",stdin);
        freopen("fir.out","w",stdout);
        memset(g,-1,sizeof(g));
        n = read(),p = read();
        rep(i,1,n)
        {
            x = read(),y = read();
            if(pduse(x,y)) printf("illegal
    "),exit(0);
            else if(pdeat(x,y,i&1))
            {
                g[x][y] = i&1;
                if(pdwin(x,y,i&1))
                {
                    (i&1) ? printf("ITer %d
    ",i) : printf("Kitty %d
    ",i);
                    return 0;
                }
            }
            else if(pddie(x,y,i&1)) printf("illegal
    "),exit(0);
            g[x][y] = i&1;
            if(pdwin(x,y,i&1))
            {
                (i&1) ? printf("ITer %d
    ",i) : printf("Kitty %d
    ",i);
                return 0;
            }
    //        printgraph();
        }
        printf("draw
    ");
        return 0;
    }
    View Code

    std:

    #include<bits/stdc++.h>
    using namespace std;
    int f[1111][1111],n,x,y,curx,cury,X,cnt;
    bool used[1111][1111],fl,cur;
    int dx[]= {1,0,-1,0},dy[]= {0,1,0,-1};
    int dxx[]= {1,-1,0,0,1,-1,1,-1},dyy[]= {0,0,1,-1,-1,1,1,-1};
    vector<pair<int,int> > v;
    void dfs(int x,int y,int ff)
    {
        used[x][y]=1;
        v.push_back(make_pair(x,y));
        for (int j=0; j<4; j++)
        {
            if (fl) return;
            int xx=x+dx[j],yy=y+dy[j];
            if (used[xx][yy]) continue;
            if (!f[xx][yy])
            {
                fl=1;
                return;
            }
            if (f[xx][yy]==ff) dfs(xx,yy,ff);
        }
    }
    bool DFS(int x,int y)
    {
        v.clear();
        fl=0;
        dfs(x,y,f[x][y]);
        if (!fl)
        {
            for (int i=0; i<v.size(); i++)
            {
                f[v[i].first][v[i].second]=0;
            }
        }
        for (int i=0; i<v.size(); i++)
        {
            used[v[i].first][v[i].second]=0;
        }
        return fl;
    }
    int main()
    {
        freopen("FIR.in","r",stdin);
        freopen("FIR.out","w",stdout);
        scanf("%d%d",&n,&X);
        for (int i=1; i<=n; i++)
        {
            scanf("%d%d",&x,&y);
            if (f[x][y])
            {
                printf("illegal
    ");
                return 0;
            }
            f[x][y]=(i&1)+1;
            if (f[x][y+1] && f[x][y+1]!=f[x][y]) DFS(x,y+1);
            if (f[x+1][y] && f[x+1][y]!=f[x][y]) DFS(x+1,y);
            if (f[x][y-1] && f[x][y-1]!=f[x][y]) DFS(x,y-1);
            if (f[x-1][y] && f[x-1][y]!=f[x][y]) DFS(x-1,y);
            if (!DFS(x,y))
            {
                printf("illegal
    ");
                return 0;
            }
            for (int j=0; j<4; j++)
            {
                curx=x;
                cury=y;
                cnt=1;
                for (int k=0; k<X; k++)
                {
                    curx+=dxx[j*2];
                    cury+=dyy[j*2];
                    if (f[curx][cury]!=f[x][y]) break;
                    cnt++;
                }
                curx=x;
                cury=y;
                for (int k=0; k<X; k++)
                {
                    curx+=dxx[j*2+1];
                    cury+=dyy[j*2+1];
                    if (f[curx][cury]!=f[x][y]) break;
                    cnt++;
                }
                if (cnt>=X)
                {
                    if (i&1) printf("ITer %d
    ",i);
                    else printf("Kitty %d
    ",i);
                    return 0;
                }
            }
        }
        printf("draw
    ");
        return 0;
    }
    View Code

    T2.maze

    期望得分30,实际得分30

    这道题考试的时候先写了30分暴力bfs,之后想到50分可以DP,但是死活没调出来……

    然后考完发现自己忘记从0枚举,然后还忘记判断不能走的格子的情况了……

    正解很简洁,我们必然要经过大对角线上的一点,从(1,1)走到大对角线上的一点最多有220种情况,同理(n,m)也一样。所以我们可以先处理(1,1)到大对角线上点的所以情况,之后从(n,m)出发汇合。至于如何存储数值,我们只需要用强无敌的map映射即可。

    看一下代码。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<utility>
    #include<map>
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    using namespace std;
    typedef long long ll;
    const int M = 100005;
    const int N = 10000005;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >='0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    int n,m,kx,a[25][25],cnt,maxn,dx[3] = {0,0,1},dy[3] = {0,1,0},dp[25][25][40005];
    ll ans;
    map <int,ll> pm[25];
    
    void dfs(int x,int y,int sum)
    {
        if(!a[x][y]) return;
        if(x + y == n + 1)
        {
        pm[x][sum]++;
        return;
        }
        if(x < n) dfs(x+1,y,sum^a[x+1][y]);
        if(y < m) dfs(x,y+1,sum^a[x][y+1]);
    }
    
    void getans(int x,int y,int sum)
    {
        if(!a[x][y]) return;
        if(x + y == n + 1)
        {
        ans += pm[x][kx^sum^a[x][y]];
        return;
        }
        if(x > 1) getans(x-1,y,sum^a[x-1][y]);
        if(y > 1) getans(x,y-1,sum^a[x][y-1]);
    }
    
    int main()
    {
        n = read(),m = read(),kx = read();
        rep(i,1,n) 
        rep(j,1,m) a[i][j] = read(),maxn = max(maxn,a[i][j]);
        if(maxn <= 10000)
        {
        dp[1][1][a[1][1]] = 1;
        rep(i,1,n)
        {
            rep(j,1,m)
            {
            if(a[i+1][j]) rep(k,0,40000) dp[i+1][j][k^a[i+1][j]] += dp[i][j][k];
            if(a[i][j+1]) rep(k,0,40000) dp[i][j+1][k^a[i][j+1]] += dp[i][j][k];
            }
        }
        printf("%d
    ",dp[n][m][kx]);
        }
        else dfs(1,1,a[1][1]),getans(n,m,a[n][m]),printf("%lld
    ",ans);
        return 0;
    }
    View Code

    T3.snowman

    期望得分30,实际得分30.

    这个题我没有什么思路,但是要求最小值最大想到二分答案,之后好像只会暴力判断了。这个复杂度其实我不会求……因为每次判断的时间非常不稳定。不过自己随机了几组5000的数据都能过,没什么问题。

    之后正解需要差分转化,但是后面涉及到SA我就不会了orz,把题解copy一下吧(听Dukelv说可以hash过?)

    考虑两个串和谐的条件:a 1 -b 1 =...=a n -b n ,可以把它改为a 1 -a 2 =b 1 -b 2 ,a 2 -a 3 =b 2 -b 3 ...a n-1 -a n =b n-1 -b n 。所以我们可以把原串差分,然后就可以把它转成字符串匹配的问题。
    考虑 Subtask 2,将差分后的串哈希,枚举两个串的起点,二分地求出它们最多能匹配几个雪人。复杂度 O(N 2 logN)
    考虑 Subtask 3,求出差分过后的串的 sa 和 lcp,考虑二分答案,记当前二分的答案为 x。在 check 时,我们枚举一个 l,求出最大的 r 使得 min(lcp[l],lcp[l+1]...lcp[r])≥x,然后判断max(sa[l]...sa[r+1])-sa[l]是否≥x 即可,这可以用 set 和权值线段树实现。复杂度 O(Nlog 2 N)
    考虑 Subtask 4,考虑 O(NlogN)地求出 sa,还是二分答案,其实在 check 的时候我们只需要考虑每一个 lcp[l]≥x...lcp[r]≥x 的串里 max(sa[l],...,sa[r+1])- min(sa[l],...,sa[r+1])是否
    ≥x 即可。复杂度 O(NlogN)。
    当然,这个题也可以用 SAM 做,对于 SAM 上的每一个点,求 出 它 right 集 合 里 的 最 大 值 mx 和 最 小 值 mn , 用min(len+1,mx-mn)更新答案即可。

    暴力代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<utility>
    #include<map>
    #include<ctime>
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    using namespace std;
    typedef long long ll;
    const int M = 500005;
    const int N = 10000005;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >='0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    
    int n,x,a[M],l,r,ans;
    
    bool pd(int p,int q,int x)
    {
        int k = a[p] - a[q];
        rep(i,1,x-1) if((a[p+i] - a[q+i]) != k) return 0;
    //    printf("%d %d
    ",p,q);
        return 1;
    }
    
    bool check(int x)
    {
        if(x > (n >> 1)) return 0;
        rep(i,1,n-(x<<1)+1)
        {
            rep(j,i+x,n-x+1) if(pd(i,j,x)) return 1;
        }
        return 0;
    }
    
    int main()
    {
        freopen("snowman.in","r",stdin);
        freopen("snowman.out","w",stdout);    
        srand(time(NULL));
        n = read();
        rep(i,1,n) a[i] = read();
        if(n <= 5000)
        {
            l = 1,r = n;
            while(l < r)
            {
                int mid = (l+r) >> 1;
                if(check(mid)) ans = mid,l = mid+1;
                else r = mid;
            }
            printf("%d
    ",ans);
        }
        else printf("%d
    ",rand()%n);
        return 0;
    }
    /*
    10 
    1 2 3 4 5 6 7 8 9 10
    */
    View Code

    std:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int s[1111111];
    int n,rank[1111111],sa[1111111],k,fst[1111111],sec[1111111],h,lcp[1111111],x[1111111],l,r,mid;
    int cmp(int i,int j,int l)
    {
        if(i+l*2>n+1 || j+l*2>n+1) return 1;
        return sec[i]!=sec[j] || sec[i + l]!=sec[j + l];
    }
    void make_sa()
    {
        for (int i=1; i<=n; i++) x[i]=s[i];
        sort(x+1,x+1+n);
        int m=unique(x+1,x+1+n)-x-1;
        for (int i=1; i<=n; i++)
            s[i]=lower_bound(x+1,x+1+m,s[i])-x;
        memset(x, 0, sizeof(x));
        for (int i=1; i<=n; i++) ++x[fst[i]=s[i]];
        for (int i=1; i<=m; i++) x[i]+=x[i - 1];
        for (int i=n; i>0; i--) sa[x[s[i]]--]=i;
        for (int i=1; i<n; i<<=1)
        {
            int p=0;
            for (int j=n-i+1; j<=n; j++) sec[++p] = j;
            for (int j=1; j<=n; j++) if(sa[j]>i) sec[++p]=sa[j] - i;
            memset(x,0,sizeof(x));
            for (int j=1; j<=n; j++) ++x[fst[sec[j]]];
            for (int j=1; j<=m; j++) x[j]+=x[j - 1];
            for (int j=n; j>0; j--) sa[x[fst[sec[j]]]--]=sec[j];
            memcpy(sec,fst,sizeof(sec));
            fst[sa[1]]=m=1;
            for (int j=2; j<=n; j++) fst[sa[j]]=(m+=cmp(sa[j - 1],sa[j],i));
        }
    }
    void make_lcp()
    {
        int h=0;
        for (int i=1; i<=n; i++) rank[sa[i]]=i;
        for (int i=1; i<=n; i++)
        {
            int j=sa[rank[i]-1];
            if (h>0) h--;
            for (; i+h<=n && j+h<=n; h++)
            {
                if (s[i+h]!=s[j+h]) break;
            }
            lcp[rank[i]-1]=h;
        }
    }
    bool check(int x)
    {
        int pos=1,mn=1e9,mx=0;
        while(pos<n && lcp[pos]<x-1) pos++;
        while(pos<n)
        {
            mn=sa[pos];
            mx=sa[pos];
            while(pos<n && lcp[pos]>=x-1)
            {
                pos++;
                mn=min(mn,sa[pos]);
                mx=max(mx,sa[pos]);
            }
            while(pos<n && lcp[pos]<x-1) pos++;
            if (mx-mn>=x) return 1;
        }
        return 0;
    }
    int rpos, mmx;
    char str[10000000];
    char readc()
    {
        if(!rpos) mmx = fread(str, 1, 10000000, stdin);
        return rpos == mmx ? 0 : str[rpos++];
    }
    int read()
    {
        int x;
        char c;
        while((c=readc())<'0' || c>'9');
        x=c-'0';
        while((c=readc())>='0' && c<='9') x=x*10+c-'0';
        return x;
    }
    int main()
    {
        freopen("snowman.in","r",stdin);
        freopen("snowman.out","w",stdout);
        n=read();
        for (int i=1; i<=n; i++) x[i]=read();
        for (int i=1; i<n; i++)
        {
            s[i]=x[i+1]-x[i];
        }
        n--;
        make_sa();
        make_lcp();
        /*for(int i = 1; i <= n; i++) printf("%d ", s[i]);
        putchar('
    ');
        for(int i = 1; i <= n; i++) printf("%d ", sa[i]);
        putchar('
    ');
        for(int i = 1; i <= n; i++) printf("%d ", lcp[i]);
        putchar('
    ');*/
        l=0;
        r=n;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if (check(mid)) l=mid+1;
            else r=mid-1;
        }
        printf("%d
    ",r);
        return 0;
    }
    View Code
  • 相关阅读:
    攻克python3-进程
    攻克python3-线程
    攻克python3-socket
    攻克python3-面向对象
    攻克python3-装饰器
    攻克python3-函数
    攻克python3-文件操作
    算法基础
    MongoDB存储基础教程
    Python操作Excle
  • 原文地址:https://www.cnblogs.com/captain1/p/9789483.html
Copyright © 2011-2022 走看看