zoukankan      html  css  js  c++  java
  • [PKUSC2018]主斗地

    暴搜

    非常暴力的搜索,以至于我都不相信我能过。

    方法是:暴力枚举所有牌型,然后暴力判断是否可行。

    暴力枚举部分:

    非常暴力:

    void dfs(int x,int l){
        if(l==0){
            flag=0;
            check(1,0,0,0,0);
            if(flag)ans++;
            return;
        }
        if(x>14)return;
        for(res i=0;i<=limit[x]&&i<=l;++i){
            jiry[x]=i;
            dfs(x+1,l-i);
        }
    }
    

    搜下来发现牌型数量不大于(3000000),因为出题人良心的把3都去掉了,所以总牌型大量缩减。

    判断部分:

    这里需要用到一个性质,如果一幅飞机或顺子可以大于另外一幅同类型的牌,那么把他拆开来也可以大于另外一幅牌拆开来。

    判断部分分两部分,先暴力搜索搜出哪些牌要被拆出来变成三张牌或四张牌。

    因为双方的总牌数都不会很大,所以直接搜只会带一个常数。

    这里要注意,只有当九条可怜出了三张牌或四张牌以后,xx网友才能出三张牌或四张牌,不然九条可怜将无法出小于xx网友的牌型。

    最后两者出的三张牌和四张牌数量必须相等,不然会有一副牌无法有对应的牌。

    void check(int x,int one,int oneortwo,int three,int four){
        if(x>14){
            if(three||four)return;
            check(one,oneortwo);
            return;
        }
        if(jiry[x]>=4){
            jiry[x]-=4;
            check(x+1,one+1,oneortwo,three,four+1);
            jiry[x]+=4;
            if(flag)return;
        }
        if(jiry[x]>=3){
            jiry[x]-=3;
            check(x+1,one,oneortwo+1,three+1,four);
            jiry[x]+=3;
            if(flag)return;
        }
        if(xx[x]>=4&&four){
            xx[x]-=4;
            check(x+1,one,oneortwo,three,four-1);
            xx[x]+=4;
            if(flag)return;
        }
        if(xx[x]>=3&&three){
            xx[x]-=3;
            check(x+1,one,oneortwo,three-1,four);
            xx[x]+=3;
            if(flag)return;
        }
        check(x+1,one,oneortwo,three,four);
    }
    

    然后再用贪心的方式判断最后的散牌是否可以。

    枚举有多少的三张牌要带一个,然后得到有多少的一张牌和多少的两张牌可以被带掉。

    对于九条可怜的牌,去掉最大的牌。对于xx网友的牌,去掉最小的牌。要先用两张牌来贪心,再用一张牌来贪心。

    剩下的牌直接扫一遍,如果在前(i)种牌中xx网友的牌比九条可怜的要多,则当前牌错误。

    void check(int one,int oneortwo){
        for(res i=0;i<=oneortwo;i++){
            memcpy(jirycpy,jiry,sizeof jiry);
            memcpy(xxcpy,xx,sizeof xx);
            res o=i+one*2,t=oneortwo-i;
            for(res j=1;j<=14;++j){
                while(xxcpy[j]>=2&&t)xxcpy[j]-=2,t--;
                while(xxcpy[j]>=1&&o)xxcpy[j]-=1,o--;
            }
            if(o||t)continue;
            o=i+one,t=oneortwo-i;
            for(res j=14;j;--j){
                while(jirycpy[j]>=2&&t)jirycpy[j]-=2,t--;
                while(jirycpy[j]>=1&&o)jirycpy[j]-=1,o--;
            }
            if(o||t)continue;
            flag=1;
            for(res j=1,now=0;j<=14;++j){
                now-=xxcpy[j];
                if(now<0){
                    flag=0;
                    break;
                }
                now+=jirycpy[j];
            }
            if(flag)return;
        }
    }
    

    然后是完整代码

    #include<bits/stdc++.h>
    #define res register int
    using namespace std;
    char str[15];
    int jiry[15],xx[15],limit[15];
    int jirycpy[15],xxcpy[15];
    int cl(char c){
        if(c=='T')return 7;
        else if(c=='J')return 8;
        else if(c=='Q')return 9;
        else if(c=='K')return 10;
        else if(c=='A')return 11;
        else if(c=='2')return 12;
        else if(c=='w')return 13;
        else if(c=='W')return 14;
        else return c-'3';  
    }
    bool flag;
    int ans;
    void check(int one,int oneortwo){
        for(res i=0;i<=oneortwo;i++){
            memcpy(jirycpy,jiry,sizeof jiry);
            memcpy(xxcpy,xx,sizeof xx);
            res o=i+one*2,t=oneortwo-i;
            for(res j=1;j<=14;++j){
                while(xxcpy[j]>=2&&t)xxcpy[j]-=2,t--;
                while(xxcpy[j]>=1&&o)xxcpy[j]-=1,o--;
            }
            if(o||t)continue;
            o=i+one,t=oneortwo-i;
            for(res j=14;j;--j){
                while(jirycpy[j]>=2&&t)jirycpy[j]-=2,t--;
                while(jirycpy[j]>=1&&o)jirycpy[j]-=1,o--;
            }
            if(o||t)continue;
            flag=1;
            for(res j=1,now=0;j<=14;++j){
                now-=xxcpy[j];
                if(now<0){
                    flag=0;
                    break;
                }
                now+=jirycpy[j];
            }
            if(flag)return;
        }
    }
    void check(int x,int one,int oneortwo,int three,int four){
        if(x>14){
            if(three||four)return;
            check(one,oneortwo);
            return;
        }
        if(jiry[x]>=4){
            jiry[x]-=4;
            check(x+1,one+1,oneortwo,three,four+1);
            jiry[x]+=4;
            if(flag)return;
        }
        if(jiry[x]>=3){
            jiry[x]-=3;
            check(x+1,one,oneortwo+1,three+1,four);
            jiry[x]+=3;
            if(flag)return;
        }
        if(xx[x]>=4&&four){
            xx[x]-=4;
            check(x+1,one,oneortwo,three,four-1);
            xx[x]+=4;
            if(flag)return;
        }
        if(xx[x]>=3&&three){
            xx[x]-=3;
            check(x+1,one,oneortwo,three-1,four);
            xx[x]+=3;
            if(flag)return;
        }
        check(x+1,one,oneortwo,three,four);
    };
    void dfs(int x,int l){
        if(l==0){
            flag=0;
            check(1,0,0,0,0);
            if(flag)ans++;
            return;
        }
        if(x>14)return;
        for(res i=0;i<=limit[x]&&i<=l;++i){
            jiry[x]=i;
            dfs(x+1,l-i);
        }
    }
    int main(){
        scanf("%s",str+1);
        int len=strlen(str+1);
        for(int i=1;i<=12;++i){
        	limit[i]=4;
        }
        limit[13]=limit[14]=1;
        memset(xx,0,sizeof xx);
        for(int i=1;i<=len;++i){
            limit[cl(str[i])]--;
            xx[cl(str[i])]++;
        }
        ans=0;
        dfs(1,17); 
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    HDU 6984
    洛谷 P6776
    C语言 error C4996: This function or variable may be unsafe
    C语言 sizeof 函数
    C语言 strlen 函数
    C语言 char 字符串
    C语言 goto 语句
    C语言 switch 语句
    C语言 do while 和 while 循环
    C语言 while 循环
  • 原文地址:https://www.cnblogs.com/zhenglier/p/10910151.html
Copyright © 2011-2022 走看看