Description
Input
第一行一个整数N(N<=100),表示玩了N次超级麻将。 接下来N行,每行100个数a1..a100,描述每次玩牌手中各种牌的数量。ai表示数字为i的牌有ai张。(0<=ai<=100)
Output
输出N行,若胡了则输出Yes,否则输出No,注意区分Yes,No的大小写!
Sample Input
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)
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)
Sample Output
Yes
Yes
No
Yes
No
题解
这道题题解很多都是用贪心+$Hash$搜索做的,其实$DP$也可以解决这道题。
我们考虑选取麻将的先后是不互相影响的。且怎么选当前牌只会影响其相邻的几张牌,我们将这些影响的状态放入方程中,保证无后效性。
令: $f[i][j][k][0/1]$ 表示“择第 $i$ 号牌时,第 $i-1$ 号牌要打出 $j$ 张,第 $i$ 号牌要打出 $k$ 张,之前选的所有牌是否( $0/1$ )选择了将(对子)”是否可行。
于是就有转移方程:
- 考虑选这i号牌做将(对子):
if (k>1) f[i][j][k][1]|=f[i][j][k-2][0];
- 考虑i号牌碰(三张相同):
if (k>2) f[i][j][k][1]|=f[i][j][k-3][1],f[i][j][k][0]|=f[i][j][k-3][0];
- 考虑i号牌杠(四张相同):
if (k>3) f[i][j][k][1]|=f[i][j][k-4][1],f[i][j][k][0]|=f[i][j][k-4][0];
- 考虑i-2,i-1,i三张牌吃(三个连续数字):
if (j>=k&&a[i-2]>=k) f[i][j][k][0]|=f[i-1][a[i-2]-k][j-k][0],f[i][j][k][1]|=f[i-1][a[i-2]-k][j-k][1];
最后结果为$f[100][a[99]][a[100]][1]$。
附的代码有个玄学的写法:当$i==1$时,$a[i-2]$越界?我也不知道它访问到哪去了,但$AC$了就苟活着吧。
人生处处是惊喜...难道不是吗?
1 #include<set> 2 #include<map> 3 #include<ctime> 4 #include<cmath> 5 #include<queue> 6 #include<stack> 7 #include<cstdio> 8 #include<string> 9 #include<vector> 10 #include<cstring> 11 #include<cstdlib> 12 #include<iostream> 13 #include<algorithm> 14 #define LL long long 15 #define RE register 16 #define IL inline 17 using namespace std; 18 19 int n,a[105]; 20 bool f[105][105][105][2]; 21 22 int main() 23 { 24 scanf("%d",&n); 25 while (n--) 26 { 27 memset(f,0,sizeof(f)); 28 for (RE int i=1;i<=100;i++) scanf("%d",&a[i]); 29 f[0][0][0][0]=1; 30 for (RE int i=1;i<=100;i++) 31 for (RE int j=0;j<=a[i-1];j++) 32 for (RE int k=0;k<=a[i];k++) 33 { 34 if (k>1) f[i][j][k][1]|=f[i][j][k-2][0]; 35 if (k>2) f[i][j][k][1]|=f[i][j][k-3][1],f[i][j][k][0]|=f[i][j][k-3][0]; 36 if (k>3) f[i][j][k][1]|=f[i][j][k-4][1],f[i][j][k][0]|=f[i][j][k-4][0]; 37 if (j>=k&&a[i-2]>=k) f[i][j][k][0]|=f[i-1][a[i-2]-k][j-k][0],f[i][j][k][1]|=f[i-1][a[i-2]-k][j-k][1]; 38 } 39 printf(f[100][a[99]][a[100]][1] ? "Yes ":"No "); 40 } 41 return 0; 42 }