• UVA 1609 Foul Play 不公平竞赛 (构(luan)造(gao)+递归)


    题意:有n支队伍(n是2的整数幂,2<=n<=4),打淘汰赛,胜者进入下一轮,其中1号队伍能打败至少一半的队伍,对于它不能打败的队伍l,一定存在一支它能够打败的队伍w,使得w能直接打败l,求一种方案保证1号队伍必胜。

    队伍分类:不能直接打败的队伍是黑色队伍,能直接打败且能打败黑色队伍的是灰色队伍。

    这里直接给出算法描述了:

    阶段1:贪心,每个不能直接打败的队伍,选一个没有匹配的能打败它的灰色队伍。

    阶段2:对于剩下的黑色队伍,任意匹配,可能会剩下一个。

    阶段3:找一个能直接打败的队伍和1号匹配

    阶段4:剩下的其他队伍任意匹配。

    对于进阶的队伍,仍然会满足之前的条件。直到1号队伍胜利为止。

    正确性请参考紫书。手写了个vec,感觉效率不比stl快多少,可能数据比较少吧。。。下标还写错了一发,尴尬。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1025;
    
    char G[maxn][maxn];
    int vec[5][maxn];
    
    
    
    int main()
    {
       // freopen("in.txt","r",stdin);
        int n, *phase = vec[4];
        while(~scanf("%d",&n)){
            for(int i = 0; i < n; i++) scanf("%s",G[i]);
    
            int *win = vec[0],*lose = vec[2],sz1= 0,sz2 = 0;
            for(int i = 1; i < n; i++){
                if(G[0][i] == '1') win[sz1++] = i;
                else lose[sz2++] = i;
            }
            int N = n,  s = 0;
            while(N > 1){
                s ^= 1;
                int *win2 = vec[s+0], *lose2 = vec[s+2], sz3 = 0,sz4 = 0;
                int sz5 = 0;
                for(int i = 0; i < sz2; i++){
                    int tlose = lose[i];
                    int j = 0;
                    for(; j < sz1; j++){
                        int &twin = win[j];
                        if(twin > 0 && G[twin][tlose] == '1') {
                            printf("%d %d
    ",twin+1,tlose+1);
                            win2[sz3++] = twin;
                            twin = 0;
                            break;
                        }
                    }
                    if(j == sz1) phase[sz5++] = tlose;
                }
    
                while(sz5>1){
                    int &a = phase[sz5-1], &b = phase[sz5-2];
                    printf("%d %d
    ",a+1,b+1);
                    if(G[a][b] == '1') lose2[sz4++] = a;
                    else  lose2[sz4++] = b;
                    sz5 -= 2;
                }
                bool flag = sz5 == 1;
                int i = 0;
                for(; i < sz1; i++) if(win[i]>0) { printf("1 %d
    ",win[i++]+1); break; }
                for(; i < sz1; i++) if(win[i]>0) { phase[sz5++] = win[i]; }
    
                i = 0;
                if(flag) {
                    int &a = phase[i], &b = phase[i+1];
                    if(G[a][b] == '1') {
                        lose2[sz4++] = a;
                    }else {
                        win2[sz3++] = b;
                    }
                    printf("%d %d
    ",a+1,b+1);
                    i += 2;
                }
    
                for(; i < sz5; i += 2){
                    int &a = phase[i], &b = phase[i+1];
                    if(G[a][b] == '1') {
                        win2[sz3++] = a;
                    }else {
                        win2[sz3++] = b;
                    }
                    printf("%d %d
    ",a+1,b+1);
                }
                sz1 = sz3; sz2 = sz4;
                win = win2; lose = lose2;
                N >>= 1;
            }
        }
        return 0;
    }
  • 相关阅读:
    Hash大法
    最小表示法
    KMP算法题集
    分块总结
    2018 雅礼国庆集训
    二分图总结
    贪心总结
    Tire树总结(模板+例题)
    工具类文章合集
    网文胡乱汇总
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4694691.html
Copyright © 2020-2023  润新知