洛谷 P2593 [ZJOI2006]超级麻将【dp】

设f[i][j][k][0/1]表示选到i时,i-1选j张,i选k张,之前选的所有牌是否选择了对子
然后分情况讨论转移即可

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=105;
int n,a[N];
bool f[N][N][N][2];
int main()
{
    scanf("%d",&n);
    while(n--)
    {
        memset(f,0,sizeof(f));
        for(int i=1;i<=100;i++) 
			scanf("%d",&a[i]);
        f[0][0][0][0]=1;
        for(int i=1;i<=100;i++)
            for(int j=0;j<=a[i-1];j++)
                for(int k=0;k<=a[i];k++)
                {
                    if(k>1) 
						f[i][j][k][1]|=f[i][j][k-2][0];
                    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];
					}
                    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];
					}
                    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];
					}
                }
		if(f[100][a[99]][a[100]][1])
			puts("Yes");
		else
			puts("No");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lokiii/p/9693852.html