bzoj1294: [SCOI2009]围豆豆Bean
题目链接
题解
对豆豆进行装压
令dp[i][j][k]表示从i,j出发,把状态为k豆豆的围起来的最小话费
spfa转移
在进行状态的转移的时候,我们需要得到下一个位置的豆豆状态
利用射线法判断是否在多边形内部,从该豆豆点向右引出一条射线,如果穿过的边界是奇数就算,偶数则不算。
异或记录奇偶转移
代码
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9') {if(c == '-' ) f = -1;c = getchar();}
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
return x * f;
}
const int maxn = 11;
int n,m;
int D,val[maxn];
int map[maxn][maxn],fs[6] = {1,0,-1,0,1} ;
char a[maxn];
int dp[maxn][maxn][1 << maxn];
int ans = 0;
struct Node {
int x,y,S;
Node(int x = 0,int y = 0,int S = 0) : x (x),y(y),S(S) {};
}loc[maxn * maxn];
//inline int Get_Node(int i ,int j) { return i * (n - 1) + j; }
int Get_Point(int x,int y,int tx,int ty,int S) {
for(int i = 0;i < D;++ i) {
int X = loc[i].x,Y = loc[i].y;
if(((x < X && tx >= X) || (x >= X && tx < X)) && y > Y)
S ^= (1<<i);
}
return S;
}
void spfa(int I,int J) {
memset(dp,0x3f,sizeof dp);
std::queue<Node>que;que.push(Node(I,J,0));
dp[I][J][0] = 0;
while(! que.empty()) {
Node cur = que.front();que.pop();
for(int j = 0;j < 4;++ j) {
int tx = cur.x + fs[j],
ty = cur.y + fs[j + 1];
if(tx > n || tx < 1 || ty > m || ty < 1 || map[tx][ty] != -1) continue;
int state = Get_Point(cur.x,cur.y,tx,ty,cur.S);
//printf("%d\n",state);
if(dp[tx][ty][state] > dp[cur.x][cur.y][cur.S] + 1) {
dp[tx][ty][state] = dp[cur.x][cur.y][cur.S] + 1;
que.push(Node(tx,ty,state)) ;
}
}
}
for(int i = 0;i < (1<<D); ++ i) {
int V = -dp[I][J][i];
for(int j = 0;j < D;++ j) {
if((1 << j) & i) V += val[j];
}
ans = std::max(ans,V);
}
}
int main() {
n = read(),m = read();D = read();
for(int i = 0;i < D;++ i) val[i] = read();
for(int i = 1;i <= n;++ i) {
scanf("%s",a + 1);
for(int j = 1;j <= m;++ j) {
if(a[j] >= '0' && a[j] <= '9') { map[i][j] = a[j] - '0' - 1;loc[map[i][j]] = Node(i,j,0); }
else if(a[j] == '#') map[i][j] = 13;
else map[i][j] = -1;
}
}
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= m;++ j)
if(map[i][j] == -1) spfa(i,j);
printf("%d\n",ans);
}