hdu 3001 Travelling (TSP问题 )

Travelling

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3905    Accepted Submission(s): 1234

Problem Description

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.

Input

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.

Output

Output the minimum fee that he should pay,or -1 if he can‘t find such a route.

Sample Input

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

Sample Output

100
90
7 

DP+状态压缩:每一个点最多仅仅能经过2次,考虑用3进制存储状态;

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 12
#define M 59050
#define LL long long
const int inf=0x1f1f1f1f;  //注意初始化值
int tri[N]= {0,1,3,9,27,81,243,729,2187,6561,19683,59049};
int g[N][N];
int dig[M][N]; //dig[i][j]记录I状态下J点是否出现,出现几次
int dp[M][N]; //dp[s][j] 在状态s下,以j为终点的最短距离
void inti()     //求出每一个状态s相应的3进制位的信息
{
    int i,j,t;
    for(i=1;i<M;i++)
    {
        for(t=i,j=1;j<=10;j++)
        {
            dig[i][j]=t%3;          //求出该状态下到达每一个的城市次数
            t/=3;
            if(!t) break;
        }
    }
}
int main()
{
    int i,j,a,b,c;
    int n,m,s;
    inti();
    while(scanf("%d%d",&n,&m)!=-1)
    {
        memset(g,inf,sizeof(g));
        memset(dp,inf,sizeof(dp));
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            g[a][b]=g[b][a]=min(c,g[a][b]);
        }
        for(i=1;i<=n;i++)      //起始状态。能够任一城市为起点。
            dp[tri[i]][i]=0;   //距离自然初始化为0
        int ans=inf;
        for(s=1;s<tri[n+1];s++)  //在s状态以i为终点时更新其它状态的值
        {
            int f=1;
            for(i=1;i<=n;i++)
            {
                if(dig[s][i]==0)     //推断当前状态S下,每一个城市是否都已到达
                    f=0;
                if(dp[s][i]==inf)
                    continue;
                for(j=1;j<=n;j++) //dp[s][i]状态到dp[s+tri[j]][j]状态
                {
                    if(g[i][j]==inf||i==j||dig[s][j]>=2)
                        continue;
                    int news=s+tri[j];
                    dp[news][j]=min(dp[news][j],dp[s][i]+g[i][j]);
                }
            }
            if(f)
                for(i=1;i<=n;i++)
                ans=min(ans,dp[s][i]);
        }
        if(ans==inf)
            ans=-1;
        printf("%d\n",ans);
    }
    return 0;
}
</pre><p></p><p></p><p><span style="font-size:18px; color:#33ccff">bfs+状态压缩:</span></p><p><span style="color:rgb(51,204,255); font-size:18px">開始时把每个点都入队,模拟3进制处理每个状态,最后+优化。

</span></p><p></p><pre code_snippet_id="479354" snippet_file_name="blog_20141004_2_7195338" name="code" class="cpp">#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
#define N 12
#define LL long long
const int inf=0x3fffffff;
int g[N][N];
int n,m,ans;
int mark[N][60000];
struct node
{
    int x,t,s,cnt;  //位置、时间、状态、个数
    friend bool operator<(node a,node b)
    {
        return a.t>b.t;
    }
};
int gettmp(int x,int k)  //得到X在3进制下的第K位是多少
{                        //推断该点是否经过了。经过了几次
    int t;
    while(x)
    {
        t=x%3;
        k--;
        if(k==0)
            break;
        x/=3;
    }
    return k?0:t;
}
void inti()      //初始化数组
{
    int i,j;
    for(i=1;i<=n;i++)
    {
        for(j=0;j<(int)pow(3,n);j++)
            mark[i][j]=inf;
    }
}
void bfs()
{
    int i;
    priority_queue<node>q;
    node cur,next;
    for(i=1;i<=n;i++)
    {
        cur.x=i;
        cur.s=pow(3,(i-1));
        cur.t=0;
        cur.cnt=1;
        q.push(cur);
        mark[i][0]=0;
    }
    while(!q.empty())
    {
        cur=q.top();
        q.pop();
        for(i=1;i<=n;i++)
        {
            if(g[cur.x][i]==inf)  //此路不通
                continue;
            next.cnt=cur.cnt;
            next.s=cur.s;
            next.t=cur.t+g[cur.x][i];
            if(ans<next.t)    //优化非常重要
                continue;
            next.x=i;
            int t=gettmp(next.s,i);  //该点经过了几次,
            if(t>=2)                 //经过2次后就不能走了
                continue;
            next.s+=pow(3,(i-1));    //该点经过次数加一
            if(t==0)                 //经过一个新景点
            {
                next.cnt++;
                if(next.cnt==n)
                {
                    ans=min(ans,next.t);
                    continue;
                }
            }
            if(next.t<mark[i][next.s])
            {
                mark[i][next.s]=next.t;
                q.push(next);
            }
        }
    }
}
int main()
{
    int a,b,c,i,j;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        for(i=0;i<=n;i++)
            for(j=1;j<=n;j++)
                g[i][j]=(i==j?

0:inf);
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            g[a][b]=g[b][a]=min(g[a][b],c);
        }
        ans=inf;
        inti();
        bfs();
        if(ans==inf)
            ans=-1;
        printf("%d\n",ans);
    }
    return 0;
}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-07-30 20:14:58

hdu 3001 Travelling (TSP问题 )的相关文章

hdu 3001 Travelling TSP变形 三进制状压dp

// hdu 3001 TSP问题的变形 // 这次到每个点最多两次,所以可以用三进制的类推 // dp[S][u]表示当前在u点访问状态为S时所得到的最小的开销 // 采用刷表法,即用当前的状态推出它所能转移的状态 // dp[S][u] 可以到达的状态为dp[S+state[v]][v](dist[u][v]!=inf) // dp[S+state[v]][v] = max(dp[S+state[v]][v],dp[S][u]+dist[u][v]); // 其中每个点最多访问2次 // 技

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

题意:有 n 个city,可以选择任一城市作为起点,每个城市不能访问超过2次, 城市之间有权值,问访问全部n个城市需要的最小权值. 思路:因为每个城市可以访问最多两次,所以用三进制表示访问的状态. 详细见代码注释!!!! #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #include<cmath> #inclu

HDU 3001 Travelling:TSP(旅行商)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题意: 有n个城市,m条双向道路,每条道路走一次需要花费路费v.你可以将任意一个城市作为起点出发,然后遍历每一个城市,并保证同一个城市最多经过2次.问你遍历这些城市的最小费用是多少. 题解: 传统的TSP问题中,每个城市只能经过一次,做法为三重for循环,分别枚举城市的state.现在所处位置i.下一步要到达的城市j. 核心Code: 1 memset(dp,-1,sizeof(dp)); 2

HDU 3001 Travelling

Travelling Time Limit: 3000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 300164-bit integer IO format: %I64d      Java class name: Main After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best

HDU 3001 Travelling 状压DP

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题意:还是环游地图的问题,只不过这回旅行者对自己有着严格的要求,地图上每个点的经过次数不能超过两次. 思路:依然是状压DP问题,根上一道很像,只不过这次对于每个点来说有三种状态,分别是未经过,经过一次,经过两次.所以要用三进制的数来进行状态压缩,这个关键点想明白了其他的和上一道基本一样了.对于我来说需要注意的是:能够到达某一个点经过了两次的状态的前一个状态是这个点已经经过了一次的状态,而不是从来未

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题目大意:有n个城市,m条路,每条路都有一定的花费,可以从任意城市出发,每个城市不能经过两次以上,要求经过所有城市并且花费最少,求出最小花费. 解题思路:三进制的状态压缩DP,跟二进制还是有一点不一样的,因为三进制没有直接的位运算,还要自己先做处理利用num[i][j]记录数字i各位的三进制表示方便计算,其他的就跟二进制状态压缩没有太大区别了.还有注意: ①开始要将n个起点初始化,dp[bit

HDU 3001 Travelling (状压DP,3进制)

题意: 给出n<=10个点,有m条边的无向图.问:可以从任意点出发,至多经过同一个点2次,遍历所有点的最小费用? 思路: 本题就是要卡你的内存,由于至多可经过同一个点2次,所以只能用3进制来表示,3进制可以先将表打出来.在走的时候注意只能走2次,其他的和普通的TSP状压DP是一样的.注意点:重边,自环等等,老梗了. 1 //#include <bits/stdc++.h> 2 #include <iostream> 3 #include <cstdio> 4 #i

hdu 3001 Travelling (bfs+状态压缩)

Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3905    Accepted Submission(s): 1234 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is

状压DP [HDU 3001] Travelling

Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4166    Accepted Submission(s): 1339 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is