[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\n" : "No\n"); 27 } 28 return 0; 29 }