您的位置:首页 > 其它

HDU 3001 Travelling (三进制状态压缩DP+BFS)

2013-08-23 11:13 429 查看
题意:有n个点(n<=10),要求都经过,每个点最多经过两次,求遍历每个点的最小花费。

分析:每个点最多经过两次,则用三进制保存状态,一个好的技巧就是开个pos数组,记录每个状态用三进制表示时,每一位的情况。    枚举每个点为起点,然后每次sum值是不需要清空的,清空了反而造成了诸多重复遍历....................

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#define INF 0x7FFFFFFF
using namespace std;
int p[11];
int pos[60000][11];
int dist[11][11],sum[11][60000];
struct node {
int x,buff;
} q[1111111];
int head,tail,n,m,ans;
void init() {
for(int i=1; i<=10; i++)
for(int j=1; j<=10; j++)
if(i != j) dist[i][j] = INF;
else dist[i][j] = 0;
memset(sum,0,sizeof(sum));
}
void bfs(int v0) {
ans = INF;
// memset(sum,0,sizeof(sum));
head = 0;
tail = 0;
q[head].x = v0;
q[head++].buff = p[v0-1];
while(head != tail) {
node t = q[tail ++];
node tt;
int cnt = 0;
for(int i=0; i<=n; i++) {
if(pos[t.buff][i] >= 1) cnt++;
}
if(cnt == n) {
ans = min(ans,sum[t.x][t.buff]);
}
for(int i=1; i<=n; i++) {
if(t.x == i || dist[t.x][i] == INF) continue;
if(pos[t.buff][i-1] >= 2) continue;
if(sum[t.x][t.buff] + dist[t.x][i] >= ans) continue;
tt.buff = t.buff + p[i-1];
tt.x = i;
if(sum[i][tt.buff] != 0 && sum[i][tt.buff] > sum[t.x][t.buff] + dist[t.x][i]) {
sum[i][tt.buff] = sum[t.x][t.buff] + dist[t.x][i];
q[head++] = tt;
} else if(! sum[i][tt.buff]) {
sum[i][tt.buff] = sum[t.x][t.buff] + dist[t.x][i];
q[head++] = tt;
}
}
}
}
int main() {
int a,b,c;
for(int i=1; i<=11; i++) p[i-1] = pow(3.0,(i-1)*1.0);
for(int i=1; i<=59050; i++) {
int tmp = i,j = 0;
while(tmp) {
pos[i][j++] = tmp % 3;
tmp = tmp / 3;
}
}
while(scanf("%d%d",&n,&m) != EOF) {
init();
for(int i=0; i<m; i++) {
scanf("%d%d%d",&a,&b,&c);
if(c < dist[a][b]) {
dist[a][b] = c;
dist[b][a] = c;
}
}
int minn = INF;
for(int i=1; i<=n; i++) {
bfs(i);
minn = min(minn,ans);
}
if(minn == INF) printf("-1\n");
else printf("%d\n",minn);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: