您的位置:首页 > 产品设计 > UI/UE

UESTC 882 冬马党 --状压DP

2014-05-31 20:44 253 查看
定义:dp[i][j]为状态为j时,第i行符合条件的状态数

转移方程:dp[i][j] += dp[i-1][t] //t为上一行状态,与当前行不冲突。

从第一行开始向下枚举,每次枚举当前行的状态和上一行的状态,如果不相邻或者未被地雷占据并且两行的关系是合法的,则加上方法数。

最后res = SUM(dp
[s]) (s=0~S,为最后一行的状态)

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define Mod 1000000007
using namespace std;
#define N 100000000

//dp[i][j]:状态为j时,第i行符合条件的状态数
int wei[14];
int a[2070];
int dp[14][2070];

int checkadj(int state)
{
if(state & (state<<1))   //相邻
return 0;
return 1;
}

int checkplace(int state,int i)
{
if(state & wei[i])     //被地雷占据
return 0;
return 1;
}

int main()
{
int n,m,i,j,k,state;
scanf("%d%d",&n,&m);
memset(wei,0,sizeof(wei));
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&state);
if(!state)
wei[i] += (1<<(m-j));  //被地雷占据赋为1
}
}
int Fst = 1<<m;
k = 0;
for(state=0;state<Fst;state++)   //第一行
{
if(checkadj(state))
{
a[k++] = state;
if(checkplace(state,1))
dp[1][k-1] = 1;
}
}
for(i=2;i<=n;i++)
{
for(j=0;j<k;j++)   //枚举上一行
{
if(!checkplace(a[j],i-1))
continue;
for(state=0;state<k;state++)  //枚举这一行
{
if(!checkplace(a[state],i) || (a[j] & a[state]))
continue;
dp[i][state] = (dp[i][state] + dp[i-1][j])%N;
}
}
}
int res = 0;
for(i=0;i<k;i++)
res = (res + dp
[i])%N;
printf("%d\n",res);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: