[BZOJ1860][ZJOI2006]Mahjong(DP)

1860: [Zjoi2006]Mahjong麻将

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 412  Solved: 248
[Submit][Status][Discuss]

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)

Sample Output

Yes
Yes
No

HINT

Source

[Submit][Status][Discuss]

怎么这种题老是不会啊。。还有这个样例怎么不可复制啊。。

f[i][j][k][0/1]表示前i位,第i-1位还剩j张,第i位还剩k张,是/否用过一次对子,是否可行。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=l; i<=r; i++)
 5 using namespace std;
 6 
 7 const int N=110;
 8 int n,a[N],f[N][N][N][2];
 9 
10 int main(){
11     freopen("bzoj1860.in","r",stdin);
12     freopen("bzoj1860.out","w",stdout);
13     for (scanf("%d",&n); n--; ){
14         rep(i,1,100) scanf("%d",&a[i]);
15         memset(f,0,sizeof(f)); f[0][0][0][0]=f[0][0][0][1]=1;
16         rep(i,1,100){
17             rep(j,0,a[i-1])
18                 rep(k,0,a[i]){
19                     if (k>1) f[i][j][k][1]|=f[i][j][k-2][0];
20                     if (k>2) f[i][j][k][0]|=f[i][j][k-3][0],f[i][j][k][1]|=f[i][j][k-3][1];
21                     if (k>3) f[i][j][k][0]|=f[i][j][k-4][0],f[i][j][k][1]|=f[i][j][k-4][1];
22                     if (a[i-2]>=k && a[i-1]>=k)
23                         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];
24                 }
25         }
26         printf((f[100][a[99]][a[100]][0]|f[100][a[99]][a[100]][1]) ? "Yes
" : "No
");
27     }
28     return 0;
29 }
原文地址:https://www.cnblogs.com/HocRiser/p/8762021.html