题目链接:点击打开链接
题意:
给定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