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;
}

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

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

  1. HDU 3001 Travelling:TSP(旅行商)【节点最多经过2次】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题意: 有n个城市,m条双向道路,每条道路走一次需要花费路费v.你可以将任意一个城市作为起点出发 ...

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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题目大意:有n个城市,m条路,每条路都有一定的花费,可以从任意城市出发,每个城市不能经过两次以上 ...

  3. HDU - 3001 Travelling(三进制状压dp)

    Travelling After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best ch ...

  4. hdu 3001 Travelling(状态压缩 三进制)

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

  5. hdu 3001 Travelling (三进制)【状压dp】

    <题目链接> 题目大意: 给出n个点和m条边,求经过所有点所需的最小花费,每个点最多经过两次. 解题分析: TSP问题类型,由于此题每个点有三种状态,所以采用三进制状态压缩,0.1.2 分 ...

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

    题意: 给出n<=10个点,有m条边的无向图.问:可以从任意点出发,至多经过同一个点2次,遍历所有点的最小费用? 思路: 本题就是要卡你的内存,由于至多可经过同一个点2次,所以只能用3进制来表示 ...

  7. HDU 3001 Travelling 3进制状压dp

    题意:10个点,若干条边,边有花费,每个点最多走两次,求走过所有点,花费最少 分析:因为每个点最多走两次,所以联想到3进制,然后枚举状态,就行了(我也是照着网上大神的代码写的) #include &l ...

  8. HDU - 3001 Travelling 状压dp + 三进制 [kuangbin带你飞]专题二

    终于刷完搜索专题了. 题意:给定n个城市,每个城市参观不能超过两次,两个城市之间有道路通过需要花费X,求通过能所有城市的最小花费. 思路:每个城市有三个状态0,1,2,可用三进制存储所有城市的访问状态 ...

  9. Hdu 3001 Travelling 状态DP

    题目大意 一次旅游,经过所有城市至少一次,并且任何一座城市访问的次数不能超过两次,求最小费用 每个城市最多访问两次,用状态0,1,2标识访问次数 把城市1~N的状态按照次序连接在一起,就组成了一个三进 ...

随机推荐

  1. POJ1163 The Triangle 【DP】

    The Triangle Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 36918   Accepted: 22117 De ...

  2. Date()创建日期

    哎. .这些人变得懒惰个月...经过以上撰写博客的工作 上周五测试报告的问题.上述日期的计算是有问题.两个日期之间的差异原创1天,然而,系统将计算的差31天. (就在那一天2014年10月31日本 星 ...

  3. WEB打印的几种方案

    -------------------------------------------一  基于Web的打印方案比较分析-------------------------------- 基于web的套 ...

  4. C#语音录制

    客服小妹是如何泡到手的——C#定时提醒·语音录制·语音播放·文件转录Demo——倾情奉献!   一.需求提出 客服小妹跟我说,每天要统计新加好友数,得先记下昨天的数目,然后查看今天的数目,还要相减,打 ...

  5. 分析java.lang.NullPointerException thrown in RelativeLayout measure()

    典型的再现环境 模型: Sony Ericsson Android version: 2.3.4 StackTrace: E/AndroidRuntime( 3579): FATAL EXCEPTIO ...

  6. Windows 8 应用开发 - 磁贴

    原文:Windows 8 应用开发 - 磁贴      我们开发的应用在Win8 界面中会以磁贴形式展现,默认情况下磁贴会显示应用图标,即项目工程中的Logo.png图片文件.开发人员可按应用的需要使 ...

  7. 重新想象 Windows 8 Store Apps (5) - 控件之集合控件: ComboBox, ListBox, FlipView, ItemsControl, ItemsPresenter

    原文:重新想象 Windows 8 Store Apps (5) - 控件之集合控件: ComboBox, ListBox, FlipView, ItemsControl, ItemsPresente ...

  8. IIS7构造Gzip压缩

    IIS7构造Gzip压缩 本文来自Kevin Yang博客 作者:Kevin Yang 开启配置HTTP压缩(GZip) 在IIS7中配置Gzip压缩相比IIS6来说实在easy了很多.并且默认情况下 ...

  9. python网络爬虫学习笔记

    python网络爬虫学习笔记 By 钟桓 9月 4 2014 更新日期:9月 4 2014 文章文件夹 1. 介绍: 2. 从简单语句中開始: 3. 传送数据给server 4. HTTP头-描写叙述 ...

  10. Nutch 二次开发parse纸

    大约nutch基础知识可以参考lemo柱 nutch支持二次开发,为了满足搜索的准确性的问题,内容提取出来作为索引的内容,相应的是parse_text的数据.我使用的事nutch1.4 版本号,在cy ...