您的位置:首页 > 其它

状态压缩DP总结

2015-01-26 14:21 477 查看
POJ1185 炮兵部队问题:

在平原上才能放置炮兵,每个炮兵的上下左右2格之内都不能出现别的炮兵

可以考虑在当前行放置炮兵它的右侧和下侧绝对不会出现炮兵即可,左侧和上侧就能省去考虑

明显的状态压缩dp题,但是题目所给的有10列,因为每行都与前两行的状态有关,那么也就是根据当前,上一行,上上行3行状态来修改

dp[i][v][u]的状态方程

因为这里直接3重循环会爆,但是我们很容易发现,可以预处理一些关于行的合法状态,那么状态数就少了很多,接下来考虑的时候就省去了行上的相关影响

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 1<<6;
int dp[105]

;

void dfs(int i , int w , int v , int u , int val , int k)
{
if(k<0){
dp[i][v][u] = max(dp[i][v][u] , val);
return;
}
if(k>=2){
if(!(w&(1<<(k-1))) && !(v&(7<<(k-2))) && !(u&(1<<(k-1))))
dfs(i , w|(1<<(k-1)) , v|(7<<(k-2)) , u|(1<<(k-1)) , val+5 , k-3);
if(!(v&(7<<(k-2))) && !(u&(1<<(k-1))))
dfs(i , w , v|(7<<(k-2)) , u|(1<<(k-1)) , val+4 , k-3);
if(!(v&(7<<(k-2))) && !(u&(1<<k)))
dfs(i , w , v|(7<<(k-2)) , u|(1<<k) , val+4 , k-3);
}
if(k>=1){
if(!(w&(1<<k)) && !(v&(3<<(k-1))) && !(u&(1<<k)))
dfs(i , w|(1<<k) , v|(3<<(k-1)) , u|(1<<k) , val+4 , k-2);
if(!(w&(3<<(k-1))) && !(v&(1<<k)) && !(u&(1<<k)))
dfs(i , w|(3<<(k-1)) , v|(1<<k) , u|(1<<k) , val+4 , k-1);
}
dfs(i , w , v , u , val , k-1);
}

int main()
{
//  freopen("a.in" , "r" , stdin);
int n,m;
while(scanf("%d%d" , &n , &m) == 2)
{
memset(dp , -1 , sizeof(dp));
dp[1][(1<<m)-1][0] = 0;
for(int i=2 ; i<=n ; i++){
for(int w=0 ; w<(1<<m) ; w++){
for(int v=0 ; v<(1<<m) ; v++){
if(dp[i-1][w][v]>=0) dfs(i , w , v , 0 , dp[i-1][w][v] , m-1);
}
}
}
int ans = 0;
for(int v=0 ; v<(1<<m) ; v++)
for(int u=0 ; u<(1<<m) ; u++)
ans = max(ans , dp
[v][u]);
printf("%d\n" , ans);
}
return 0;
}


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