洛谷1879-[USACO06NOV]Corn Fields G-玉米田(状压dp)
作者:互联网
题目描述
输入描述
输出描述
输入样例
2 3
1 1 1
0 1 0
输出样例
9
互不侵犯 的青春版(?),本题省去了对于数量上限的要求,因此仅需使用二维状态 f [ i ] [ j ] 即可,其中 i 表示种到了第 i 行,j 表示该行是以第 j 种状态种地。
对于每一行,同样进行初始化枚举每一种状态是否符合种地要求,若存在相邻的 1 则将该状态标为非法。
状态转移方程:
f [ i ] [ j ] = f [ i − 1 ] [ x ] f[i][j]=f[i-1][x] f[i][j]=f[i−1][x]
其中 x 表示上一行采用的种地状态。
本题中唯一的特殊点是:某些地可能不允许种。因此对于即将转移到的第 i 行,需要考虑状态 j 是否与这一行的土地状态相匹配,若改行的某个土地为不允许播种,而状态 j 在该土地上种植了作物,则该状态与该行冲突,直接忽略即可。
由于数据范围不是很大,直接在答案处取模即可。
参考代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=15,M=1<<14;
int g[N][N];//存放土地情况
bool st[M];
ll f[N][M];
int mod=1e8;
int n,m;
bool check(int col,int now){
if(!st[now])
return false;
for(int j=1;j<=m;j++){
if((g[col][j]==0)&&(((now>>(m-j))&1)==1))
return false;
}
return true;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>g[i][j];
}
}
//预处理
for(int i=0;i<1<<m;i++){
st[i]=true;
for(int j=0;j<m;j++){
if(((i>>j)&1)&&(i>>(j+1)&1))
st[i]=false;
}
}
f[0][0]=1;
for(int i=1;i<=n+1;i++){
for(int j=0;j<1<<m;j++){
for(int x=0;x<1<<m;x++){
if(!check(i,j))
continue;
if((j&x)!=0)
continue;
f[i][j]=(f[i-1][x]+f[i][j]);
}
}
}
cout<<f[n+1][0]%mod;
return 0;
}
标签:状态,玉米田,洛谷,int,状压,st,种地,return,false 来源: https://blog.csdn.net/laysan/article/details/121308648