您的位置:首页 > 其它

poj 1185 炮兵阵地 状态压缩dp

2012-09-29 10:11 429 查看
之前想做黑书上的那个状态压缩dp,不会写

退而求其次,写了这个,也纠结也好久,其实只要想好, 算好时间复杂度,大胆写就好,想的时候总觉得这样会超时,循环好多什么什么的,又懒得看解题报告,所以拖了好久……结果写出来就A掉了,219ms~

/*
dfs求出每一行的状态,最多一行的状态是60中,算不出的可以用10个p跑一下看看~
dp[i][j][k] = dp[i-1][k][t] + rowcount[i][j]
dp[i][j][k] 表示第i行选择状态为j, i-1行为k状态
rowcount[i][j] 表示 第i行选择j状态时,此行炮兵的个数
rowstate[i][j]为第i行,第j种状态(10位,二进制压缩为一个数)
tot[i]为每行共有多少状态数
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int m, n, mit[110][15], dp[110][65][65];
int rowstate[110][65], rowcount[110][65], ans, bin[15], tot[110];
void dfs(int st, int r, int id, int aa){
int tmp;
for(int i= id+1; i<= m; i++){
if( mit[r][i]== 0){
tmp = st;
tmp|= bin[i];
rowstate[r][ans] = tmp;
rowcount[r][ans++] = aa+ 1;
dfs(tmp, r, i + 2, aa+ 1);
}
}
}
void dynamic(){
int i, j, k, t, mm;
memset(dp, 0, sizeof( dp));
tot[0] = 1;
for( i= 0; i< tot[1]; i++){
dp[1][i][0] = rowcount[1][i];
}
for( i= 2; i<= n; i++){
mm= 0;
for( j= 0; j< tot[i]; j++){
for( k= 0; k< tot[i-1]; k++){
if( (rowstate[i][j]&rowstate[i-1][k]) == 0 ){
for( t= 0; t<tot[i-2]; t++){
if((rowstate[i][j]& rowstate[i-2][t]) == 0 && (rowstate[i-1][k] & rowstate[i-2][t]) == 0){
//这里忘记写max,WA一次
dp[i][j][k] = max( dp[i][j][k], dp[i-1][k][t] + rowcount[i][j]);
}
}
}
}
}
//cout<<i<<"  "<<mm<<endl;
}
for( i= 0, mm= 0; i<tot
; i++){
for( j= 0; j<tot[n-1]; j++){
mm = max( mm, dp
[i][j]);
}
}
printf("%d\n", mm);
}
int main(){
//freopen("1.txt", "r", stdin);
int i, j, k, st, mm;
for( i= 0; i<= 10; i++)
bin[i] = (1<<i);
while( scanf("%d%d", &n, &m) != EOF){
memset( mit, 0, sizeof( mit));
getchar();
for( i= 1; i<= n; i++){
for( j= 1; j<= m; j++)
mit[i][j] = (getchar() == 'H');
getchar();
}
for( i= 1; i<= n; i++){
ans = 0, st= 0;
rowstate[i][ans] = st;
rowcount[i][ans++] = 0;
dfs( st, i, 0, 0);
tot[i] = ans;
//cout<<i<<"  "<<ans<<endl;
}
dynamic();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: