uva 11210 Chinese Mahjong 中国麻将 dfs回溯
2015-09-26 23:53
351 查看
题目:https://uva.onlinejudge.org/external/112/11210.pdf
详见注释:
注意这道题的搜索方式,我之前虽然与答案一样,先找出将,再dfs,但是写的远远比答案麻烦。
中国麻将,有意思。
详见注释:
注意这道题的搜索方式,我之前虽然与答案一样,先找出将,再dfs,但是写的远远比答案麻烦。
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #include<climits> #include<queue> #include<vector> #include<map> #include<sstream> #include<set> #include<stack> #include<cctype> #include<utility> #pragma comment(linker, "/STACK:102400000,102400000") #define PI 3.1415926535897932384626 #define eps 1e-10 #define sqr(x) ((x)*(x)) #define FOR0(i,n) for(int i=0 ;i<(n) ;i++) #define FOR1(i,n) for(int i=1 ;i<=(n) ;i++) #define FORD(i,n) for(int i=(n) ;i>=0 ;i--) #define lson num<<1,le,mid #define rson num<<1|1,mid+1,ri #define MID int mid=(le+ri)>>1 #define zero(x)((x>0? x:-x)<1e-15) #define mk make_pair #define _f first #define _s second using namespace std; //const int INF= ; typedef long long ll; //const ll inf =1000000000000000;//1e15; //ifstream fin("input.txt"); //ofstream fout("output.txt"); //fin.close(); //fout.close(); //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); const int INF =0x3f3f3f3f; const int maxn= 50 ; const int N= 34 ; //const int maxm= ; //by yskysker123 map<string ,int >mp; int cnt[maxn]; char s[15][8]; bool ok; char name[50][8]= {"", "1T","2T","3T","4T","5T","6T","7T","8T","9T", "1S","2S","3S","4S","5S","6S","7S","8S","9S", "1W","2W","3W","4W","5W","6W","7W","8W","9W", "DONG","NAN","XI","BEI", "ZHONG","FA","BAI" }; void Getmap() { mp["1T"]= 1 ;mp["2T"]= 2 ;mp["3T"]= 3 ;mp["4T"]= 4 ;mp["5T"]= 5 ;mp["6T"]= 6 ; mp["7T"]= 7 ;mp["8T"]= 8 ;mp["9T"]= 9 ; mp["1S"]= 10 ;mp["2S"]= 11 ;mp["3S"]= 12;mp["4S"]= 13 ;mp["5S"]= 14 ;mp["6S"]= 15 ; mp["7S"]= 16 ;mp["8S"]= 17 ;mp["9S"]= 18 ; mp["1W"]= 19 ;mp["2W"]= 20 ;mp["3W"]= 21;mp["4W"]= 22;mp["5W"]= 23;mp["6W"]= 24; mp["7W"]= 25 ;mp["8W"]= 26;mp["9W"]= 27; mp["DONG"]=28;mp["NAN"]=29;mp["XI"]=30;mp["BEI"]=31; mp["ZHONG"]=32;mp["FA"]=33;mp["BAI"]=34; } void cope(int i) { int x=mp[ (string)s[i] ]; cnt[x]++; } bool dfs(int step) //统计每种牌的个数cnt[],再根据cnt[]来加加减减进行dfs,比我原来的 对手里的14张牌进行顺次考虑 要简单的多。 { if(step==5) return true; //作顺子 for(int i=1;i<=27-2;i++) { if(i%9 ==8|| i%9 ==0) continue;//错误写法 :if(i%9 +1 ==8|| i%9 +1 ==9) continue; if(!cnt[i] || !cnt[i+1] || !cnt[i+2]) continue; cnt[i]--;cnt[i+1]--;cnt[i+2]--; if(dfs(step+1)) return true; cnt[i]++;cnt[i+1]++;cnt[i+2]++; } //作刻子 for(int i=1;i<=N;i++) { if(cnt[i]<3) continue; cnt[i]-=3; if(dfs(step+1) ) return true; cnt[i]+=3; } return false; } bool check(int x) //注意这道题的搜索方式,我之前虽然与答案一样,先找出将,再dfs,但是写的远远比答案麻烦。 { memset(cnt,0,sizeof cnt); //每次检查一种麻将 都初始化,直接将保存在数组里的输入信息再一次读取就行了,省去(开多个数组来避免回溯一半就跳出)的麻烦 for(int i=1;i<=13;i++) { cope(i); } if(cnt[x]==4) return false; //最大坑点,如果某个麻将已有四种颜色,那么你是不可能摸到这种麻将的。 cnt[x]++; //将子: for(int i=1;i<=N;i++) { if(cnt[i]<2) continue; cnt[i]-=2; if(dfs(1)) return true; cnt[i]+=2; //回溯----dfs精髓 } return false; } void work() { ok=0; for(int i=1;i<=34;i++) { if(check(i)) ok=1, printf(" %s",name[i]); } if(!ok) printf(" Not ready"); putchar('\n'); } int main() { int kase=0; mp.clear(); Getmap(); while(~scanf("%s",s[1])&&strcmp(s[1],"0")!=0) { for(int i=2;i<=13;i++) { scanf("%s",s[i]); } printf("Case %d:",++kase); work(); } return 0; }
中国麻将,有意思。
相关文章推荐
- Google Java编程风格指南
- 【JAVA】数字相加
- 布局
- C++: 函数返回非引用类型与返回引用类型
- 405个手机项目
- Postman用法简介-Http请求模拟工具
- Android之万能适配器Adapter的使用
- reactjs
- hdu-5475-An easy problem-线段树求乘积
- Sublime Text 汉化以及package control的安装与使用
- sharedPreferences
- linux内核之sys接口device_add详解
- TProcedure,TMethod,TNotifyEvent,TWndMethod的区别,并模拟点击按钮后发生的动作
- JavaScript高级程序设计之引用类型之基本包装类型第5.6讲笔记
- 汇编总结:左移,右移指令
- 线段树专题
- 死锁
- mybaits标签
- 关于sigsetjmp和siglongjmp
- 字符串加密