您的位置:首页 > 编程语言 > Go语言

LightOJ - 1057 Collecting Gold(状压DP)

2015-10-28 23:02 323 查看
题目大意:给出一张地图,刚开始在X这个位置,问走到所有的g后返回原点的最小移动次数

解题思路:用dp[i][j]表示走的状态是j,当前停在i需要移动的次数

接着转移就可以了

#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
using namespace std;

const int N = 20;
const int S = (1 << 16) + 10;

struct Node {
int pos, s;
Node() {}
Node(int pos, int s): pos(pos), s(s) {}
};

int dp
[S];
int cnt, n, m, cas = 1;
int x
, y
;
char map
;

void init() {
cnt = 0;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
scanf("%s", map);
for (int j = 0; j < m; j++) {
if (map[j] == 'x') {
x[0] = i;
y[0] = j;
}
else if (map[j] == 'g') {
x[++cnt] = i;
y[cnt] = j;
}
}
}
}

int dis(int pos, int i) {
int row = abs(x[pos] - x[i]);
int col = abs(y[pos] - y[i]);
return max(row, col);
}

void solve() {
memset(dp, 0x3f, sizeof(dp));
queue<Node> Q;
Q.push(Node(0, 1));
dp[0][1] = 0;

int All = (1 << (cnt + 1)) - 1;
while (!Q.empty()) {
int pos = Q.front().pos;
int s = Q.front().s;
Q.pop();

if (s == All) {
dp[0][All] = min(dp[0][All], dp[pos][All] + dis(pos, 0));
continue;
}

for (int i = 1; i <= cnt; i++) {
if (s & (1 << i)) continue;
if (dp[i][s | (1 << i)] > dp[pos][s] + dis(i, pos)) {
dp[i][s | (1 << i)] = dp[pos][s] + dis(i, pos);
Q.push(Node(i, s | (1 << i)));
}
}
}
printf("Case %d: %d\n", cas++, dp[0][All]);
}

int main() {
int test;
scanf("%d", &test);
while (test--) {
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: