【CF 534F】Game

来源:互联网 发布:nba2kol熊猫挂机软件 编辑:程序博客网 时间:2024/05/22 13:29

Description

这里写图片描述

Solution

CF上是输出任意一个方案,这题改成了输出方案数。
其实用一个六维DP很显然的。但很麻烦。
考虑优化一下暴搜。
以为行数最多只有5行,所以可以枚举每列的状态然后再判断行的状态。
所以要先预处理每列要使值为x的所有状态。
然后把得出的一行的状态hash一下,记忆化一下,设f[x][y][z]表示做到第x列,x-1列的状态是y,现在的hash值是z,如果这个状态不为-1(初始状态为-1,表示没出现过),那么直接退出f[x][y][z]。

Code

#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=21,mo=1000000007;int i,j,k,l,t,n,m,ans;int hang[maxn],lie[maxn],shu[1000][1000];int ci[11],er[11],f[21][32][170000],a[21];//bool bz[21][32][170000];int dfs(int x,int y){    int t=0,i;    fo(i,1,n)t+=a[i]*ci[i-1];    if(x==m+1){        fo(i,1,n)if(a[i]!=hang[i])return 0;        return 1;    }    if(f[x][y][t]>=0)return f[x][y][t];    f[x][y][t]=0;    fo(i,1,n){        if(a[i]>hang[i]||a[i]+(m-x+2)/2<hang[i])return 0;    }    fo(i,1,shu[lie[x]][0]){        fo(j,1,n)if(!(y&er[j])&&(shu[lie[x]][i]&er[j]))a[j]++;        f[x][y][t]=(f[x][y][t]+dfs(x+1,shu[lie[x]][i]))%mo;        fo(j,1,n)if(!(y&er[j])&&(shu[lie[x]][i]&er[j]))a[j]--;    }    return f[x][y][t];}int main(){    scanf("%d%d",&n,&m);    fo(i,1,n)scanf("%d",&hang[i]);    fo(i,1,m)scanf("%d",&lie[i]);ci[0]=1;    fo(i,1,n)er[i]=1<<i-1,ci[i]=ci[i-1]*11;    fo(i,0,(1<<n)-1){        int u=0;        fo(j,1,5)if((er[j]&i)&&(!(er[j-1]&i)))u++;        shu[u][++shu[u][0]]=i;    }    memset(f,255,sizeof(f));    printf("%d\n",dfs(1,0));}
1 0
原创粉丝点击