poj3001
2016-03-27 16:25
281 查看
D - Travelling
Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d
& %I64u
Submit Status Practice HDU
3001
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
n(n<=10)个城市,m条道路,可以从任意一个城市出发,然后遍历所有城市,每个城市最多经过2次,问最短路程是多少
这个问题和旅行商问题类似,但是不同之处在于每个城市最多可以走2次,旅行商问题每个城市只走1次,然后回到出发点,一般都是从0点出发回到0点;在旅行商问题中用二进制表示该城市走过没走过得状态,在本题中需要用三进制表示走过的状态;
具体见代码
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <stdlib.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int state[12]= {0,1,3,9,27,81,243,729,2187,6561,19683,59049}; ///几个直达状态
int mp[12][12];
int dp[12][60000];///3^10<60000
///3进制表示,dp[i][j]表示到i点的j状态 每个点状态有0(没走过)1(走了一次)2(走了两次)
int visit[12][60000];
int m,n;
int min(int a,int b)
{
if(a<b)
return a;
return b;
}
void init()///visit[i][j]表示j状态到达i点几次
{
memset(visit,0,sizeof(visit));
for(int i=0; i<60000; i++
{
int t=i;
for(int j=1; j<=10; j++)
{
visit[j][i]=t%3;
t/=3;
if (!t) break;
}///类似与二进制状态的初始化,只不过这里不能用位运算
}
}
void solve()
{
int ans=inf;
for(int i=0; i<=n; i++) dp[i][state[i]]=0;
for(int i=0; i<state[n+1]; i++)///所有点仅经过这个点且只经过一次的
{
bool f=1;
for(int j=1 ; j<=n; j++)
{
if (!visit[j][i]) f=0;
if (dp[j][i]==inf) continue;
for(int k=1; k<=n; k++)
{
if (k==j || mp[j][k]==inf || visit[k][i]>=2) continue;
dp[k][i+state[k]]=min(dp[j][i]+mp[j][k],dp[k][i+state[k]]);
///k行(state[k]表示只经过k状态与i状态(原状态)之和)
///表示j点i状态通过的方法更新至k点[i+state[k]]状态的方法
}
}
if (f)
{
for(int j=1; j<=n; j++)
{
ans=min(ans,dp[j][i]);///更新最小值
}
}
}
if (ans==inf) ans=-1;///无法完成
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
memset(dp,inf ,sizeof(dp));
memset(mp,inf ,sizeof(mp));
for(int i=0; i<m; i++)
{
int u,v,num;
scanf("%d%d%d",&u,&v,&num);
mp[u][v]=mp[v][u]=min(mp[u][v],num);
}
solve();
}
return 0;
}
Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d
& %I64u
Submit Status Practice HDU
3001
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
n(n<=10)个城市,m条道路,可以从任意一个城市出发,然后遍历所有城市,每个城市最多经过2次,问最短路程是多少
这个问题和旅行商问题类似,但是不同之处在于每个城市最多可以走2次,旅行商问题每个城市只走1次,然后回到出发点,一般都是从0点出发回到0点;在旅行商问题中用二进制表示该城市走过没走过得状态,在本题中需要用三进制表示走过的状态;
具体见代码
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <stdlib.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int state[12]= {0,1,3,9,27,81,243,729,2187,6561,19683,59049}; ///几个直达状态
int mp[12][12];
int dp[12][60000];///3^10<60000
///3进制表示,dp[i][j]表示到i点的j状态 每个点状态有0(没走过)1(走了一次)2(走了两次)
int visit[12][60000];
int m,n;
int min(int a,int b)
{
if(a<b)
return a;
return b;
}
void init()///visit[i][j]表示j状态到达i点几次
{
memset(visit,0,sizeof(visit));
for(int i=0; i<60000; i++
{
int t=i;
for(int j=1; j<=10; j++)
{
visit[j][i]=t%3;
t/=3;
if (!t) break;
}///类似与二进制状态的初始化,只不过这里不能用位运算
}
}
void solve()
{
int ans=inf;
for(int i=0; i<=n; i++) dp[i][state[i]]=0;
for(int i=0; i<state[n+1]; i++)///所有点仅经过这个点且只经过一次的
{
bool f=1;
for(int j=1 ; j<=n; j++)
{
if (!visit[j][i]) f=0;
if (dp[j][i]==inf) continue;
for(int k=1; k<=n; k++)
{
if (k==j || mp[j][k]==inf || visit[k][i]>=2) continue;
dp[k][i+state[k]]=min(dp[j][i]+mp[j][k],dp[k][i+state[k]]);
///k行(state[k]表示只经过k状态与i状态(原状态)之和)
///表示j点i状态通过的方法更新至k点[i+state[k]]状态的方法
}
}
if (f)
{
for(int j=1; j<=n; j++)
{
ans=min(ans,dp[j][i]);///更新最小值
}
}
}
if (ans==inf) ans=-1;///无法完成
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
memset(dp,inf ,sizeof(dp));
memset(mp,inf ,sizeof(mp));
for(int i=0; i<m; i++)
{
int u,v,num;
scanf("%d%d%d",&u,&v,&num);
mp[u][v]=mp[v][u]=min(mp[u][v],num);
}
solve();
}
return 0;
}
相关文章推荐
- 五子棋AI算法第八篇-重构代码
- win10系统调用架构分析
- 绘画的色彩基础教程
- 初探双向链表
- substring()方法是如何工作
- HDU 5651(排列组合,逆元)
- LeetCode 50. Pow(x, n),求幂算法
- 【追求进步】从上往下打印二叉树
- 约瑟夫问题
- 电机随笔
- (转)ASP.NET禁用刷新重复提交Backspace键
- Git常用命令
- JMM——运行时数据区
- (转)ASP.net中Timer无刷新定时器.
- 第五周项目一 三角形类雏形(4)
- GPS模块应用程序
- CodeForces 579A Raising Bacteria (水)
- 整理音乐
- mac下给vim添加行号
- HDU 1242 rescue (优先队列模板题)