您的位置:首页 > 其它

HDU 3001 三进制 状压dp

2014-09-02 16:02 274 查看

Travelling

Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3789 Accepted Submission(s): 1182

[align=left]Problem Description[/align]
After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best choice!He has decided to visit n cities(he insists on seeing all the cities!And he does not mind which city being his start station because superman can bring him to any city at first but only once.), and of course there are m roads here,following a fee as usual.But Mr Acmer gets bored so easily that he doesn't want to visit a city more than twice!And he is so mean that he wants to minimize the total fee!He is lazy you see.So he turns to you for help.

[align=left]Input[/align]
There are several test cases,the first line is two intergers n(1<=n<=10) and m,which means he needs to visit n cities and there are m roads he can choose,then m lines follow,each line will include three intergers a,b and c(1<=a,b<=n),means there is a road between a and b and the cost is of course c.Input to the End Of File.

[align=left]Output[/align]
Output the minimum fee that he should pay,or -1 if he can't find such a route.

[align=left]Sample Input[/align]

2 1 1 2 100 3 2 1 2 40 2 3 50 3 3 1 2 3 1 3 4 2 3 10

[align=left]Sample Output[/align]

100 90 7

[align=left]Source[/align]
2009 Multi-University Training Contest 11 - Host by HRBEU

[align=left]Recommend[/align]
gaojie

转自:http://blog.csdn.net/azheng51714/article/details/7773862

题意:

ACMer 想要游玩n个城市,告诉我们每个城市间的旅行费用,并且要求每个城市最多走两遍!问最小花费是多少 ?!

思路:

典型的TSP问题,唯一的变化就是走两遍!

解法:

利用三进制将边点j 在点集i 出现的次数表示成 tir[i][j];

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<vector>
#include<set>

#define N 1005
#define M 100000
#define inf 1000000007
#define mod 1000000007
#define mod2 100000000
#define ll long long
#define maxi(a,b) (a)>(b)? (a) : (b)
#define mini(a,b) (a)<(b)? (a) : (b)

using namespace std;

int n;
int m;
int tri[12] ={0,1,3,9,27,81,243,729,2187,6561,19683,59049};
int dig[59050][11];  //dig[state][k_dig]  状态state的第k位是多少
int dp[59050][11];
int d[15][15];
int ans;
int flag;

void ini1()
{
int o,j,t;
for(o=0;o<59049;o++){
t=o;
for(j=0;j<10;j++){
dig[o][j]=t%3;
t/=3;
}
}
}

void ini()
{
int a,b;
int c;
int i;
ans=-1;
memset(dp,-1,sizeof(dp));
memset(d,-1,sizeof(d));
while(m--){
scanf("%d%d%d",&a,&b,&c);
if(d[a][b]==-1){
d[a][b]=c;
d[b][a]=c;
}
else{
d[a][b]=min(d[a][b],c);
d[b][a]=min(d[b][a],c);
}
}

for(i=1;i<=n;i++){
dp[ tri[i] ][i-1]=0;
}
}

void solve()
{
int o,j,te,k;
for(o=1;o<tri[n+1];o++){
flag=1;
for(j=0;j<n;j++){
if(dig[o][j]==0){
flag=0;continue;
}
te=o-tri[j+1];
for(k=0;k<n;k++){
if(dig[te][k]==0) continue;
if(d[k+1][j+1]==-1) continue;
if(dp[te][k]==-1) continue;
if(dp[o][j]==-1){
dp[o][j]=dp[te][k]+d[k+1][j+1];
}
else{
dp[o][j]=min(dp[o][j],dp[te][k]+d[k+1][j+1]);
}
}
}

// printf(" o=%d flag=%d\n",o,flag);
if(flag==0) continue;
for(j=0;j<n;j++){
if(dp[o][j]==-1) continue;
if(ans==-1){
ans=dp[o][j];
}
else{
ans=min(ans,dp[o][j]);
}
}

}
}

void out()
{
//for(int o=0;o<tri[n+1];o++){
//    for(int j=0;j<n;j++) printf(" o=%d j=%d dp=%d\n",o,j,dp[o][j]);
// }
printf("%d\n",ans);
}

int main()
{
ini1();
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
//scanf("%d",&T);
// for(int cnt=1;cnt<=T;cnt++)
// while(T--)
while(scanf("%d%d",&n,&m)!=EOF)
{
ini();
solve();
out();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: