题目链接:点击打开链接
题意:
给定13张各不相同的扑克牌,问最少需要几手打出
每手打出的牌必须符合以下任意标准之一:
1、任意单张
2、相同数字2张
3、相同数字3张
4、相同数字4张
5、相同数字3张+相同数字2张
6、连续5个及5个以上的数字
思路:
状压dp,dp[i]表示选了i的状态的最小牌数
然后要预处理出能一次打出的状态,这样不会t。。
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <stdio.h> #include <vector> using namespace std; #define inf 1000000 #define maxn (1<<13) struct node{ int num; char c; void put(){ if(num==14)printf("A"); else if(2<= num && num <= 9) printf("%d",num); else if(num==10)printf("T"); else if(num == 11)printf("J"); else if(num==12)printf("Q"); else printf("K"); printf("%c",c); } }a[15]; void put(int u){ for(int i = 0; i < 13 && u; i++){ if(u&1) { a[i].put(); u>>=1; u ? printf(" ") : puts(""); } else u>>=1; } } int dp[maxn], pre[maxn], all; int Stack[20], top; void siz(int x){ top = 0; for(int i = 0; i < 13 && x; i++) { if(x&1) Stack[top++] = i; x>>=1; } } int vis[15]; int ok(int u){ siz(u); memset(vis, 0, sizeof vis); int dui = 0, fir= 15, ed = 0; for(int i = 0; i < top; i++) { if(vis[ a[Stack[i]].num ]==0) { dui++; } vis[ a[Stack[i]].num ] ++; fir = min(fir, a[Stack[i]].num); ed = max(ed, a[Stack[i]].num); } if(dui==1 && top<=4) return 1; if(top == 5 && dui==2) { if(vis[fir] ==4 || vis[ed] == 4)return -1; return 1; } if(top>=5 && dui==top && (dui == (ed-fir+1))) return 1; return -1; } vector<int>G; int dfs(int u){ if(dp[u]!=-1) return dp[u]; int ans = inf; for(int i = 0; i < G.size(); i++) { int v = G[i]; if((v&u)==v) { int tmp = dfs(u^v) +1; if(ans>tmp) pre[u] = u^v, ans = tmp; } } return dp[u] = ans; } int main() { int T;scanf("%d",&T); all = maxn-1; while( T--) { for(int i = 0; i < 13; i++) { char s[10]; scanf("%s",s); if(s[0]=='A')a[i].num = 14; else if('2' <= s[0] &&s[0]<='9') a[i].num = s[0]-'0'; else if(s[0]=='T') a[i].num = 10; else if(s[0]=='J') a[i].num = 11; else if(s[0]=='Q') a[i].num = 12; else a[i].num = 13; a[i].c = s[1]; } dp[0] = 0; G.clear(); for(int i = 1; i <= all; i++) { dp[i] = ok(i); if(dp[i]==1)G.push_back(i); } memset(pre, -1, sizeof pre); cout<<dfs(all)<<endl; int u = all; while(1) { if(pre[u] == -1) { put(u); break; } else put( u - pre[u] ); u = pre[u]; } } return 0; } /* 99 Aa 2a 3d 4d 5d 6d 7d 8d 9d Ta Ja Qd Kd 2h 3c 4d 5d 6s Th Qc Qs Ad Tc Ts 9c 9d 2h 3h 4h 5h 6d 7s 8h 8d 8c 8s 9c Td Js 2a 2a 3d 4d 5d 6d 7d 8d 9d Ta Ja Qd Kd 2a 2a 2d 2d 5d 6d 7d 8d 9d Ta Ja Qd Kd 2a 2a 4a 4a 6a 6a 8a 8a 9a 9a 9a Qa Ta 2a 2a 4a 4a 6a 6a 8a 8a 9a 9a Qa Qa Ta 2a 2a 3d 4d 5d 6d 7d 8d 9d Ta Ja Qd Kd 2a 3a 4a 5a 7a 8a 9a Ta Qa Ka Aa 2a 2a 2a 2a 2a 2a 7a 8a 9a Ta Qa Ka Aa 3a 4a */
Spoj 9894 Tichu 状压dp,布布扣,bubuko.com
原文地址:http://blog.csdn.net/qq574857122/article/details/37777841