华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1212|回复: 4
打印 上一主题 下一主题

P2668 斗地主

[复制链接]

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
跳转到指定楼层
楼主
发表于 2018-5-11 11:16:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
https://www.luogu.org/problemnew/show/P2668

题目描述
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关 系根据牌的数码表示如下: 3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王 ,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由 nn 张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。

现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。

需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:




本题数据随机,不支持hack,要hack或强力数据请点击这里

输入输出格式
输入格式:
第一行包含用空格隔开的2个正整数 T,nT,n ,表示手牌的组数以及每组手牌的张数。

接下来 TT 组数据,每组数据 nn 行,每行一个非负整数对 a_i,b_ia ,表示一张牌,其中 a_ia表示牌的数码, b_ib表示牌的花色,中间用空格隔开。特别的,我们用 11 来表示数码 A, 1111 表示数码 J, 1212 表示数码 Q, 1313 表示数码 K;黑桃、红心、梅花、方片分别用 1-4 来表示;小王的表示方法为 0 1 ,大王的表示方法为 0 2 。

输出格式:
共 TT 行,每行一个整数,表示打光第 ii 组手牌的最少次数。

输入输出样例
输入样例#1:
1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1
输出样例#1:
3
输入样例#2:
1 17
12 3
4 3
2 3
5 4
10 2
3 3
12 2
0 1
1 3
10 1
6 2
12 1
11 3
5 2
12 4
2 2
7 2
输出样例#2:
6
说明
样例1说明

共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张牌(黑桃5)以及对子牌(黑桃A以及方片A)在3次内打光。

对于不同的测试点, 我们约定手牌组数T与张数n的规模如下:



数据保证:所有的手牌都是随机生成的。


回复

使用道具 举报

1

主题

15

帖子

101

积分

注册会员

Rank: 2

积分
101
沙发
发表于 2018-7-4 16:58:51 | 只看该作者
一开始直接搜索tle,后来看题解说搜索顺子,散牌贪心打出来,没考虑拆牌打,不过随机数据弱……
这种题打得真的累……
  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. const int N = 20;
  6. using namespace std;
  7. int p[N],c[N];
  8. int n,t,ans;
  9. int other()
  10. {
  11.     memset(c,0,sizeof(c));
  12.     for(int i=0; i<=13; i++)
  13.         c[p[i]]++;
  14.     int t=0;
  15.     while(c[4] && c[2]>1)
  16.         c[4]--, c[2]-=2, t++;
  17.     while(c[4] && c[1]>1)
  18.         c[4]--, c[1]-=2, t++;
  19.     while(c[4] && c[2])
  20.         c[4]--, c[2]--, t++;
  21.     while(c[3] && c[2])
  22.         c[3]--, c[2]--, t++;
  23.     while(c[3] && c[1])
  24.         c[3]--, c[1]--, t++;
  25.     return t + c[1] + c[2] + c[3] + c[4];
  26. }

  27. void dfs(int now)
  28. {
  29.     if(now >= ans)
  30.         return ;
  31.     int add = other();
  32.     if(now + add < ans)
  33.         ans = now + add;
  34.     for(int i=2; i<=13; i++)
  35.     {
  36.         int j=i;
  37.         while(p[j] >= 3)
  38.             j++;
  39.         if(j-i >= 2)
  40.         {
  41.             for(int m=i+1; m<=j-1; m++)
  42.             {
  43.                 for(int k=i; k<=m; k++)
  44.                     p[k]-=3;
  45.                 dfs(now+1);
  46.                 for(int k=i; k<=m; k++)
  47.                     p[k]+=3;
  48.             }
  49.         }
  50.     }
  51.     for(int i=2; i<=13; i++)
  52.     {
  53.         int j=i;
  54.         while(p[j]>=2)
  55.             j++;
  56.         if(j-i>=3)
  57.         {
  58.             for(int m=i+2; m<=j-1; m++)
  59.             {
  60.                 for(int k=i; k<=m; k++)
  61.                     p[k]-=2;
  62.                 dfs(now+1);
  63.                 for(int k=i; k<=m; k++)
  64.                     p[k]+=2;
  65.             }
  66.         }
  67.     }
  68.     for(int i=2; i<=13; i++)
  69.     {
  70.         int j=i;
  71.         while(p[j]>=1)
  72.             j++;
  73.         if(j-i>=3)
  74.         {
  75.             for(int m=i+4; m<=j-1; m++)
  76.             {
  77.                 for(int k=i; k<=m; k++)
  78.                     p[k]--;
  79.                 dfs(now+1);
  80.                 for(int k=i; k<=m; k++)
  81.                     p[k]++;
  82.             }
  83.         }
  84.     }
  85. }

  86. int main()
  87. {
  88.     cin>>t>>n;
  89.     while(t--)
  90.     {
  91.         memset(p,0,sizeof(p));
  92.         for(int i=1; i<=n; i++)
  93.         {
  94.             int a, b;
  95.             cin>>a>>b;
  96.             if(a==1)
  97.                 a=13;
  98.             else if(a)
  99.                 a--;
  100.             p[a]++;
  101.         }
  102.         ans=n;
  103.         dfs(0);
  104.         cout<<ans<<endl;
  105.     }
  106.     return 0;
  107. }
复制代码
回复 支持 反对

使用道具 举报

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
板凳
 楼主| 发表于 2018-7-4 17:25:19 | 只看该作者
好牛! 此题很锻炼你们的手上的功夫
回复 支持 反对

使用道具 举报

1

主题

15

帖子

101

积分

注册会员

Rank: 2

积分
101
地板
发表于 2018-7-4 18:06:28 | 只看该作者
本帖最后由 lyc 于 2018-7-4 18:08 编辑

加强版数据太强了……疯狂特判(因为还有可以拆的牌,不过整体还是一样,改一下散牌)然而我之前漏了好多,,,debug好久,部分特判参考题解
  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. const int N = 20;
  6. using namespace std;
  7. int p[N],c[N];
  8. int n,t,ans;
  9. int other(){//打散牌
  10.     int t = 0;
  11.     int c[10]; bool boom = 0;//炸弹
  12.     memset(c, 0, sizeof(c));
  13.     if(p[0] == 2) boom = 1;
  14.     c[1] += p[0];//王分开算
  15.     for(int i=1; i<=13; i++) c[p[i]] ++;
  16.     while(!c[3] && c[4] >= 2 && c[1] == 1 && c[2] == 1) c[4]-=2, c[1] --, c[2] --, t += 2;
  17.     while(!c[3] && c[4] >= 2 && c[1] == 2 && c[2] == 2) c[4]-=2, c[1] -=2, c[2] -=2, t += 2;
  18.     while(!c[2] && c[3] >= 2 && c[4] == 1 && c[1] == 1) c[3]-=2, c[1] --, c[4] --, t += 2;
  19.     if(c[3] + c[4] > c[1] + c[2])
  20.         while(c[4] && c[2] && c[3]) c[2]--, c[3]--, c[1]++, c[4]--,t++;
  21.     if(c[3] + c[4] > c[1] + c[2])
  22.         while(c[4] && c[1] && c[3]) c[1]--, c[3]--, c[2]++, c[4]--,t++;//以上拆牌打更优
  23.     if(c[3] % 3 == 0 && c[1] + c[2] <= 1)//拆三张
  24.         while(c[3] > 2) c[3] -= 3, t += 2;
  25.     while(c[4] && c[2] >= 2) c[4] --, c[2] -= 2, t++;//四带二对
  26.     while(c[4] && c[1] >= 2) c[4] --, c[1] -= 2, t++;//四带二
  27.     while(c[4] && c[2] >= 1) c[4] --, c[2] --  , t++;//四带一对
  28.     while(c[3] && c[2]) c[3] --, c[2] --, t++;
  29.     while(c[3] && c[1]) c[3] --, c[1] --, t++;
  30.     while(c[4] >= 2 && c[3]) c[4] -= 2, c[3] --, t+=2;
  31.     while(c[3] >= 2 && c[4]) c[3] -= 2, c[4] --, t+=2;//拆三和炸弹
  32.     while(c[3] >= 3) c[3] -= 3, t+=2;//三张三也能拆orz
  33.     while(c[4] >= 2) c[4]-=2, t++;
  34.     if(boom && c[1] >= 2) return t + c[1] + c[2] + c[3] + c[4] - 1;
  35.     return t + c[1] + c[2] + c[3] + c[4];
  36. }
  37. void dfs(int now)
  38. {
  39.     if(now >= ans)
  40.         return ;
  41.     int add = other();
  42.     if(now + add < ans)
  43.         ans = now + add;
  44.     for(int i=2; i<=13; i++)
  45.     {
  46.         int j=i;
  47.         while(p[j] >= 3)
  48.             j++;
  49.         if(j-i >= 2)
  50.         {
  51.             for(int m=i+1; m<=j-1; m++)
  52.             {
  53.                 for(int k=i; k<=m; k++)
  54.                     p[k]-=3;
  55.                 dfs(now+1);
  56.                 for(int k=i; k<=m; k++)
  57.                     p[k]+=3;
  58.             }
  59.         }
  60.     }
  61.     for(int i=2; i<=13; i++)
  62.     {
  63.         int j=i;
  64.         while(p[j]>=2)
  65.             j++;
  66.         if(j-i>=3)
  67.         {
  68.             for(int m=i+2; m<=j-1; m++)
  69.             {
  70.                 for(int k=i; k<=m; k++)
  71.                     p[k]-=2;
  72.                 dfs(now+1);
  73.                 for(int k=i; k<=m; k++)
  74.                     p[k]+=2;
  75.             }
  76.         }
  77.     }
  78.     for(int i=2; i<=13; i++)
  79.     {
  80.         int j=i;
  81.         while(p[j]>=1)
  82.             j++;
  83.         if(j-i>=3)
  84.         {
  85.             for(int m=i+4; m<=j-1; m++)
  86.             {
  87.                 for(int k=i; k<=m; k++)
  88.                     p[k]--;
  89.                 dfs(now+1);
  90.                 for(int k=i; k<=m; k++)
  91.                     p[k]++;
  92.             }
  93.         }
  94.     }
  95. }

  96. int main()
  97. {
  98.     cin>>t>>n;
  99.     while(t--)
  100.     {
  101.         memset(p,0,sizeof(p));
  102.         for(int i=1; i<=n; i++)
  103.         {
  104.             int a, b;
  105.             cin>>a>>b;
  106.             if(a==1)
  107.                 a=13;
  108.             else if(a)
  109.                 a--;
  110.             p[a]++;
  111.         }
  112.         ans=n;
  113.         dfs(0);
  114.         cout<<ans<<endl;
  115.     }
  116.     return 0;
  117. }
复制代码
回复 支持 反对

使用道具 举报

0

主题

1

帖子

61

积分

注册会员

Rank: 2

积分
61
5#
发表于 2020-1-16 11:43:10 | 只看该作者
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int t,n,x,y,ans;
  4. int sum[25];
  5. int ans2[25];
  6. void dfs(int v)
  7. {
  8.     if(v>=ans)return;
  9.     int k=0;
  10.     for(int i=3;i<=14;i++)
  11.     {
  12.         if(sum[i]==0)k=0;
  13.         else
  14.         {
  15.             k++;
  16.             if(k>=5)
  17.             {
  18.                 for(int j=i;j>=i-k+1;j--)
  19.                 {
  20.                     sum[j]--;
  21.                 }
  22.                 dfs(v+1);
  23.                 for(int j=i;j>=i-k+1;j--)
  24.                 {
  25.                     sum[j]++;
  26.                 }
  27.             }
  28.         }
  29.     }
  30.     k=0;
  31.     for(int i=3;i<=14;i++)
  32.     {
  33.         if(sum[i]<=1)k=0;
  34.         else
  35.         {
  36.             k++;
  37.             if(k>=3)
  38.             {
  39.                 for(int j=i;j>=i-k+1;j--)
  40.                 {
  41.                     sum[j]-=2;
  42.                 }
  43.                 dfs(v+1);
  44.                 for(int j=i;j>=i-k+1;j--)
  45.                 {
  46.                     sum[j]+=2;
  47.                 }
  48.             }
  49.         }
  50.     }
  51.     k=0;
  52.     for(int i=3;i<=14;i++)
  53.     {
  54.         if(sum[i]<=2)k=0;
  55.         else
  56.         {
  57.             k++;
  58.             if(k>=2)
  59.             {
  60.                 for(int j=i;j>=i-k+1;j--)
  61.                 {
  62.                     sum[j]-=3;
  63.                 }
  64.                 dfs(v+1);
  65.                 for(int j=i;j>=i-k+1;j--)
  66.                 {
  67.                     sum[j]+=3;
  68.                 }
  69.             }
  70.         }
  71.     }
  72.     for(int i=2;i<=14;i++)
  73.     {
  74.         if(sum[i]<=3)
  75.         {
  76.             if(sum[i]<=2)continue;
  77.             sum[i]-=3;
  78.             for(int j=2;j<=15;j++)
  79.             {
  80.                 if(!(sum[j]<=0 || i==j))
  81.                 {
  82.                     sum[j]--;
  83.                     dfs(v+1);
  84.                     sum[j]++;
  85.                 }
  86.             }
  87.             for(int j=2;j<=14;j++)
  88.             {
  89.                 if(!(sum[j]<=0 || i==j))
  90.                 {
  91.                     sum[j]-=2;
  92.                     dfs(v+1);
  93.                     sum[j]+=2;
  94.                 }
  95.             }
  96.             sum[i]+=3;
  97.         }
  98.         else
  99.         {
  100.             sum[i]-=3;
  101.             for(int j=2;j<=15;j++)
  102.             {
  103.                 if(!(sum[j]<=0 || i==j))
  104.                 {
  105.                     sum[j]--;
  106.                     dfs(v+1);
  107.                     sum[j]++;
  108.                 }
  109.             }
  110.             for(int j=2;j<=14;j++)
  111.             {
  112.                 if(!(sum[j]<=1 || i==j))
  113.                 {
  114.                     sum[j]-=2;
  115.                     dfs(v+1);
  116.                     sum[j]+=2;
  117.                 }
  118.             }
  119.             sum[i]+=3;
  120.             sum[i]-=4;
  121.             for(int j=2;j<=15;j++)
  122.             {
  123.                 if(!(sum[j]<=0 || i==j))
  124.                 {
  125.                     sum[j]--;
  126.                     for(int k=1;k<=14;k++)
  127.                     {
  128.                         if(!(sum[k]<=0 || j==k))
  129.                         {
  130.                             sum[k]--;
  131.                             dfs(v+1);
  132.                             sum[k]++;
  133.                         }
  134.                     }
  135.                     sum[j]++;
  136.                 }
  137.             }
  138.             for(int j=2;j<=14;j++)
  139.             {
  140.                 if(!(sum[j]<=1 || i==j))
  141.                 {
  142.                     sum[j]-=2;
  143.                     for(int k=1;k<=13;k++)
  144.                     {
  145.                         if(!(sum[k]<=1 || j==k))
  146.                         {
  147.                             sum[k]-=2;
  148.                             dfs(v+1);
  149.                             sum[k]+=2;
  150.                         }
  151.                     }
  152.                     sum[j]+=2;
  153.                 }
  154.             }
  155.             sum[i]+=4;
  156.         }
  157.     }
  158.     for(int i=2;i<=15;i++)
  159.     {
  160.         if(sum[i])
  161.         {
  162.             v++;
  163.         }
  164.     }
  165.     ans=min(ans,v);
  166. }
  167. int main()
  168. {
  169.     cin>>t>>n;
  170.     for(int i=1;i<=t;i++)
  171.     {
  172.         ans=0x7fffffff;
  173.         memset(sum,0,sizeof(sum));
  174.         for(int i=1;i<=n;i++)
  175.         {
  176.             scanf("%d%d",&x,&y);
  177.             if(x==0)
  178.             {
  179.                 sum[15]++;
  180.             }
  181.             else if(x==1)
  182.             {
  183.                 sum[14]++;
  184.             }
  185.             else
  186.             {
  187.                 sum[x]++;
  188.             }
  189.         }
  190.         dfs(0);
  191.         ans2[i]=ans;
  192.     }
  193.     for(int i=1;i<=t;i++)
  194.     {
  195.         cout<<ans2[i]<<endl;
  196.     }
  197.     return 0;
  198. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-12-26 02:15 , Processed in 0.201724 second(s), 25 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表