赞
踩
写了有五六道状态压缩dp的题,本菜发现这种题目其实和线性dp差不多,只不过是多了一个状态压缩,即将某个状态压缩到一串二进制中;
先看题:
因为行数很小,所以不难想到是状态压缩dp;
这道题和洛谷的炮兵阵地很像,都是一行的状态可以牵扯到上两个状态,所以我们在对i行进行状态转移方程的时候,我们得考虑第i-1和i-2行的状态,然后这道题目从某种意义上来说,比炮兵阵地要难一些,因为这个还有一个马的个数限制,所以我们得开4个维度的dp数组;
我们先明确一下,状态集合的定义,即dp数组的定义:
f[i][j][k][z]表示第i行的状态为j,i-1行的状态为k,且1~i行总共有z头马;
然后我们就可以想状态转移方程了,这个很简单,只要第i、i-1、i-2行互不干扰,那么我们就有:
【我们即第i行状态为j,i-1行状态为k,i-2行状态为z,且前1~i行总共有q头马,第i行的马有p头】
这里记录一下自己踩的坑吧,本菜刚开始的时候是用了滚动数组优化的,但是这里本菜忘了一件事情:滚动数组在解决求方案数的dp中要初始化,即将之前用过的空间初始化,要不然会叠加以前计算过的状态;
但是最后本菜发现空间完全够用,所以就没用滚动数组优化了;
另外还有一个坑,那就是,如果我们发现i和i-1行冲突了,那么就不用枚举下去了,直接枚举i-1行的下一个状态,否则以下的循环会建立在i-1和i行冲突的基础之上,如果在状态转移的同一个循环里进行判断,那么不会影响结果,但会浪费大量的时间,甚至tle
那么接下来就是代码了:
- #include<iostream>
- #include<algorithm>
- #define ll long long
- using namespace std;
-
- const int N=110,M=1<<6,mod=1e9+7;
-
- struct p{
- int n=0;//棋子个数
- }st[M+10];
-
- ll f[N][M][M][21];//表示第i行状态为j,第i-1行状态为k的方案数,且有z头马的方案数
- int n,m,p;
- ll ans;
-
- void init(){//初始化每一个状态
-
- for(int i=0;i<1<<n;i++){
- for(int j=0;j<n;j++)
- if(i>>j&1) st[i].n++;
- }
-
- }
-
- bool jud(int i,int j){
-
- return ((i>>2)&j)||((i<<2)&j)||((j<<2)&i)||((j>>2)&i);
- }
-
- bool jud1(int i,int j){
-
- return ((i>>1)&j)||((i<<1)&j)||((j<<1)&i)||((j>>1)&i);
- }
- int main(){
-
- cin>>n>>m>>p;
-
- init();
-
- for(int i=0;i<1<<n;i++){//枚举第1行
-
- f[1][i][0][st[i].n]++;
- }
-
- for(int i=0;i<1<<n;i++){//枚举第2行
- for(int j=0;j<1<<n;j++){
- for(int k=0;k<=p;k++){
-
- if(st[j].n>k) continue;
-
- if(jud(i,j)) continue;
-
- f[2][j][i][k]+=f[1][i][0][k-st[j].n];
-
- }
- }
- }
-
- for(int i=3;i<=m;i++){//枚举每一行
- for(int j=0;j<1<<n;j++){//i->st
- for(int k=0;k<1<<n;k++){//i-1->st
-
- if(jud(j,k)) continue;
-
- for(int z=0;z<1<<n;z++){//i-2->st
-
- if(jud1(j,z)||jud(k,z)) continue;
-
- for(int q=0;q<=p;q++){
-
- if(st[j].n>q) continue;
-
- f[i][j][k][q]+=f[i-1][k][z][q-st[j].n]%mod;
- f[i][j][k][q]%=mod;
- }
- }
- }
- }
- }
-
- for(int i=0;i<1<<n;i++){
- for(int j=0;j<1<<n;j++){
-
- if(jud(i,j)) continue;
-
- ans+=f[m][i][j][p];
- ans%=mod;
- }
- }
-
- cout<<ans%mod;
-
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。