hdu 1565 状态压缩DP

这题可以用最大流做,为了练DP就用状态压缩了。我一开始只想到一个O(n*2^n*2^n)的方法,效率太低,看了某大牛的解题报告后,才将算法优化到O(n^2*2^n)。

不过就这样还WA了好几次,原因是代码中一句

if ((k & t) == 0)我开始写成了if (k & t == 0)

没有注意到位运算符的优先级是低于逻辑运算符的,谨记谨记!

/*
* hdu1565/win.cpp
* Created on: 2011-10-4
* Author : ben
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 22;
const int MAX_STATE = 1 << 20 + 1;
int map[MAXN][MAXN];
/**
* 用了滚动数组,否则应为dp[MAXN][MAXN][MAX_STATE]
* 从上到下,从左到右填,dp[i][j][k]表示填到第i行第j列状态为k时的最大值
*/
int dp[2][MAX_STATE];
int N, state;

int work() {
int ans, t, p;
memset(dp, 0, sizeof(dp));
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
t = 1 << j;
p = (i * N + j) % 2;
for (int k = 0; k < state; k++) {
if ((k & t) == 0) {
//第j位为0
dp[1 - p][k] =
dp[p][k] > dp[p][k + t] ? dp[p][k] : dp[p][k + t];
} else if (j > 0 && (k & (t >> 1))) {
//第j-1位为1,非法,因为是滚动数据,此处赋值为0即可
dp[1 - p][k] = 0;
} else {
//当前结果应为:第j-1位为0,上一行第j位也为0的最大值加上当前位置的数值
dp[1 - p][k] = dp[p][k - t] + map[i][j];
}
}
}
}
ans = -1;
p = (N * N) % 2;
for (int k = 0; k < state; k++) {
if (dp[p][k] > ans) {
ans = dp[p][k];
}
}
return ans;
}

int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
while (scanf("%d", &N) == 1) {
state = 1 << N;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
scanf("%d", &map[i][j]);
}
}
printf("%d\n", work());
}
return 0;
}



posted @ 2011-10-05 09:54  moonbay  阅读(164)  评论(0编辑  收藏  举报