题目链接:http://codeforces.com/contest/375/problem/C
题意:
.是空地 #是墙, 12-8(连续)是宝藏,每个宝藏价值是下面对应位置的数字
从起点出发,走出一个闭合曲线回到终点 , 获得闭合曲线内的所有宝藏
闭合曲线内不能有 B(地雷)
S是起点+终点
闭合曲线内不能有 B(地雷)
S是起点+终点
雷和宝藏个数 不超过8个
走一步要扣一块钱,问最后能赚到多少钱
思路:
BFS + 射线
判断宝藏是否在闭合曲线内,可以判断经过了宝藏下方的次数(只需要判断经过下方次数即可,因为起点终点相同,所以经过上方次数与下方次数要么相同要么±2
关键的一点:奇偶数相同)
所以我们可以得到一个结论: 对于某点是否在闭合曲线内,我们可以判断 曲线穿过该点下方的次数(奇数次就是 在曲线内 )
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
#define N 21
struct node{
int x, y, st;
node(int a=0,int b=0,int c=0):x(a),y(b),st(c){}
}S;
char mp[N][N];
int V[8][2], cnt;//宝藏和地雷坐标 cnt 宝藏和地雷数
int number[8], value[8];//number[cnt] >=0为宝藏编号 -1为地雷
int f[N][N][1<<8], step[4][2] = {1,0, -1, 0, 0,1, 0,-1};
int n, m;
bool valid(int x,int y){return 0<=x && x<n && 0<=y && y<m &&( mp[x][y] == '.' || mp[x][y] == 'S');}
int get(int x,int y,int nowy,int ST){
for(int i = 0; i < cnt; i++)
if(x>V[i][0] && ((y == V[i][1] && nowy == V[i][1]+1)||(nowy == V[i][1] && y == V[i][1]+1)))
ST ^= 1<<i;
return ST;
}
int BFS(){
memset(f, -1, sizeof(f));
queue<node>q; q.push(S);
f[S.x][S.y][0] = 0;
while(!q.empty())
{
node u = q.front(); q.pop();
for(int i = 0; i < 4; i++)
{
node v = u; v.x += step[i][0], v.y += step[i][1];
if(!valid(v.x, v.y))continue;
v.st = get(v.x, v.y, u.y, u.st);
if(f[v.x][v.y][v.st] != -1)continue;
f[v.x][v.y][v.st] = f[u.x][u.y][u.st] +1;
q.push(v);
}
}
int ans = 0;
for(int i = 0;i<(1<<cnt);i++)if(f[S.x][S.y][i]!=-1){
bool bomb = false;
int sum = 0;
for(int j = 0; j < cnt; j++)if(i & (1<<j)){
if(number[j] == -1){bomb = true; break;}
sum += value[number[j]];
}
if(bomb)continue;
ans = max(ans, sum - f[S.x][S.y][i]);
}
return ans;
}
void init(){
cnt = 0;
int baozhang = 0;
memset(number, -1, sizeof(number));
for(int i = 0; i < n; i ++){
scanf("%s",mp[i]);
for(int j = 0; j < m; j++) if(mp[i][j]=='B')
{
V[cnt][0] = i; V[cnt++][1] = j;
} else if('1'<=mp[i][j] && mp[i][j] <='8')
{
V[cnt][0] = i; V[cnt][1] = j;
number[cnt++] = mp[i][j] - '1';
baozhang++;
}
else if(mp[i][j] == 'S')
{
S.x = i, S.y = j; S.st = 0;
}
}
for(int i = 0; i < baozhang; i++)scanf("%d",&value[i]);
}
int main() {
int i, j;
while(~scanf("%d %d",&n,&m)){
init();
printf("%d\n", BFS());
}
return 0;
}
/*
4 4
....
.S1.
....
....
10
7 7
.......
.1###2.
.#...#.
.#.B.#.
.3...4.
..##...
......S
100
100
100
100
7 8
........
........
....1B..
.S......
....2...
3.......
........
100
-100
100
1 1
S
10 11
........S..
...........
5........1.
.7#........
...64.#....
...........
..........#
.2.........
.....3.....
...........
-9
33
9
-20
12
10
-29
*/