WOJ 1619

武大校赛的一个题目,先简单总结一下比赛,第一次出去去现场赛,难免遇到一些问题。。这次主要问题就两个吧,2h挂机以后发现了模板题结果没带模板。。看到模拟题迟迟没有动手试图用奇淫技巧去过模板题。。。其实老老实实写模拟说不定还好一些呢。。。时间分配感觉不是很好,和平常用三个机器确实差很多,以后继续努力吧!来年再战。


这个就是当时的麻将题,题意是化简的麻将规则,然后给你一副牌看看能不能胡,这题一张一张搜应该也可以,毕竟每种的合法接临牌就那么几个,有时间试一下似乎更快。。后来听群里说可以枚举子集,于是自己写了个状压的记忆化来枚举,每次拿出三个看看可以不可以就行了,不过复杂度还是不太会计算,这里优化的技巧是预处理出来每个状态的1的个数。。。题比较长,代码能力有待提升。


#include <iostream>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
int lim=0;
int dp[1<<12];
int has[1<<12];
vector<string> v;
string vv[12];
map<string,int> mp;
string ans[3];
int ccc;
int p3(int x){
    ccc=0;
    for(int i=0;i<12;i++){
        if((x>>i)&1)
            ans[ccc++]=vv[i];
    }
    if(ans[0]==ans[1]&&ans[1]==ans[2])
        return 1;
    if(ans[0][1]!=ans[1][1]||ans[1][1]!=ans[2][1]||ans[0][1]!=ans[2][1])
        return 0;
    ans[0][0]+=2;
    ans[1][0]+=1;
    if(ans[0]==ans[1]&&ans[1]==ans[2])
        return 1;
    return 0;
}
int man=0;

int ncnt(int x){
    int ret=0;
    while(x){
        x=x&(x-1);
        ret++;
    }
    return ret;
}
int k;
int DP(int sit){
    if(dp[sit]!=-1)
        return dp[sit];
    if(has[sit]==3){
        dp[sit]=p3(sit);
        return dp[sit];
    }
    for(int i=(sit&(sit-1));i;i=((i-1)&sit)){
        if(has[i]%3==0)
            dp[sit]=max(DP(i)+DP(sit-i),dp[sit]);
    }
    return dp[sit];
}

int p(){
    map<string,int>::iterator it=mp.begin();
    string s1;
    string s2;
    int i,ii,cnt,cc;
    vector<string>::iterator st;
    for(;it!=mp.end();it++){
        if(it->second>=2){
            memset(dp,-1,sizeof(dp));
            cnt=0;
            ii=0;
            st=v.begin();
            for(;st!=v.end();st++){
                if(*st==it->first&&cnt<2){
                    cnt++;
                    continue;
                }
                vv[ii++]=*st;
            }
            cc=1;
            for(int i=0;i<12;i++){
                if(vv[i].size()==1){
                    if(mp[vv[i]]<3){
                        cc=0;
                        break;
                    }
                }
                else{
                    s1=vv[i];
                    s2=vv[i];
                    s1[0]+=1;
                    s2[0]-=1;
                    if(mp[vv[i]]<3&&mp.find(s1)==mp.end()&&mp.find(s2)==mp.end()){
                        cc=0;
                        break;
                    }
                }
            }
            sort(vv,vv+12);
            if(cc&&DP(man)==4){
                return 1;
            }
        }
    }
    return 0;
}

int p13(){
    if(mp.size()==13&&
       mp.find("1w")!=mp.end()&&mp.find("9w")!=mp.end()&&
       mp.find("1t")!=mp.end()&&mp.find("9t")!=mp.end()&&
       mp.find("1b")!=mp.end()&&mp.find("9b")!=mp.end()&&
       mp.find("w")!=mp.end()&&mp.find("e")!=mp.end()&&mp.find("s")!=mp.end()&&mp.find("n")!=mp.end()&&
       mp.find("f")!=mp.end()&&mp.find("z")!=mp.end()&&mp.find("b")!=mp.end())
        return 1;
    else
        return 0;
}

int p7(){
    if(mp.size()==7){
        map<string,int>::iterator it=mp.begin();
        for(;it!=mp.end();it++){
            if(it->second!=2)
                return 0;
        }
        return 1;
    }
    return 0;
}

int main()
{
    int t;
    cin>>t;
    for(int i=0;i<12;i++){
        man+=(1<<i);
    }
    for(int i=0;i<(1<<12);i++){
        has[i]=ncnt(i);
    }
    string s;
    while(t--){
        mp.clear();
        v.clear();
        for(int i=0;i<14;i++){
            cin>>s;
            mp[s]++;
            v.push_back(s);
        }
        int bo=0;
        bo=p13();
        if(bo==1){
            cout<<"Yes
";
            continue;
        }
        bo=p7();
        if(bo==1){
            cout<<"Yes
";
            continue;
        }
        bo=p();
        if(bo==1){
            cout<<"Yes
";
        }
        else
            cout<<"No
";
    }
    return 0;
}


原文地址:https://www.cnblogs.com/zhangxianlong/p/10672579.html