[ZJOI2006]超级麻将

题目描述

很多人都知道玩麻将,当然也有人不知道,呵呵,不要紧,我在这里简要地介绍一下麻将规则:

普通麻将有砣、索、万三种类型的牌,每种牌有1~9个数字,其中相同的牌每个有四张,例如1砣~9砣,1索~9索,1万~9万各有4张,所以共36*3=108张牌。胡牌时每人有14张牌,其中只要某人手里有若干句话(就是同种类型的牌连续三张或同种牌三张),另外再加上一对,即可胡牌。当然如果全是对,叫七小对,也可以胡牌。下图是连三张示例。

要判断某人是否胡牌,显然一个弱智的算法就行了,某中学信息学小组超级麻将迷想了想,决定将普通麻将改造成超级麻将。

所谓超级麻将没有了砣、索、万的区分,每种牌上的数字可以是1~100,而每种数字的牌各有100张。另外特别自由的是,玩牌的人手里想拿多少张牌都可以,好刺激哦!

刺激归刺激,但是拿多了怎么胡牌呢?

超级麻将规定只要一个人手里拿的牌是若干句话(三个连续数字的牌各一张组成一句话,三张或者四张同样数字的牌也算一句话),再加上一对相同的牌,就算胡了。

作为信息学竞赛选手的你,麻烦你给这位超级麻将迷编个程序,判断能否胡牌。

输入输出格式

输入格式:

输入文件第一行一个整数N(N<=100),表示玩了N次超级麻将。

接下来N行,每行100个数a1..a100,描述每次玩牌手中各种牌的数量。ai表示数字为i的牌有ai张。(0<=ai<=100)

输出格式:

输出N行,若胡了则输出Yes,否则输出No,注意区分Yes,No的大小写!

输入输出样例

输入样例#1:
3
2 4 0 0 0 0 0 …… 0(一共98个0)
2 4 2 0 0 0 0 …… 0(一共97个0)
2 3 2 0 0 0 0 …… 0(一共97个0)
输出样例#1:
Yes
Yes
No
题解:dp
f[i][j][k][1,0]表示第i个数,选j个,第i-1个数选k个有无对子
1.打出一个对子f[i][j][k][1]|=f[i][j-2][k][0]
2.打出一句话(3个)f[i][j][k][]|=f[i][j-3][k][]
3.打出4个f[i][j][k][]|=f[i][j-4][k][]
4.最复杂的地方,还有玄学
f[i][j][k][]|=f[i-1][k-j][a[i-2]-j][]
不知为何这里条件不能打i>=2,打上就错,不打就对,应该是某种边界转移
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int f[101][101][101][2],a[101];
 7 int main()
 8 {int T,i,j,k;
 9      cin>>T;
10      while (T--)
11      {
12          memset(f,0,sizeof(f));
13          for (i=1;i<=3;i++)
14          {
15              scanf("%d",&a[i]);
16         }
17         f[0][0][0][0]=1;
18           for (i=1;i<=100;i++)
19           {
20               for (j=0;j<=a[i-1];j++)
21               {
22                   for (k=0;k<=a[i];k++)
23                   {
24                       if (k>1) 
25                       f[i][k][j][1]|=f[i][k-2][j][0];
26                       if (k>2)
27                       f[i][k][j][0]|=f[i][k-3][j][0],f[i][k][j][1]|=f[i][k-3][j][1];
28                       if (k>3)
29                       f[i][k][j][0]|=f[i][k-4][j][0],f[i][k][j][1]|=f[i][k-4][j][1];
30                       if (j>=k&&a[i-2]>=k)
31                     {
32                      f[i][k][j][0]|=f[i-1][j-k][a[i-2]-k][0];
33                        f[i][k][j][1]|=f[i-1][j-k][a[i-2]-k][1];
34                       }
35                 }
36             }
37           }
38          if (f[100][a[100]][a[99]][1]) cout<<"Yes
";
39          else cout<<"No
";
40      }
41 }



原文地址:https://www.cnblogs.com/Y-E-T-I/p/7258518.html