设为首页 加入收藏

TOP

Spoj 9894 Tichu 状压dp
2015-07-20 18:07:36 来源: 作者: 【 】 浏览:6
Tags:Spoj 9894 Tichu 状压

题目链接:点击打开链接

题意:

给定13张各不相同的扑克牌,问最少需要几手打出

每手打出的牌必须符合以下任意标准之一:

1、任意单张

2、相同数字2张

3、相同数字3张

4、相同数字4张

5、相同数字3张+相同数字2张

6、连续5个及5个以上的数字


思路:

状压dp,dp[i]表示选了i的状态的最小牌数

然后要预处理出能一次打出的状态,这样不会t。。

#include 
  
   
#include 
   
     #include 
    
      #include 
     
       #include 
      
        #include 
       
         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
        
         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<
         
          

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++ 11开发环境搭建(Windows Pla.. 下一篇HDU 1829 A Bug's Life

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: