hdu 5418 Victor and World

click here~~

                                        ***Victor and World***


Problem Description
After trying hard for many years, Victor has finally received a pilot license. To have a celebration, he intends to buy himself an airplane and fly around the world. There are n countries on the earth, which are numbered from 1 to n. They are connected by m undirected flights, detailedly the i-th flight connects the ui-th and the vi-th country, and it will cost Victor's airplane wi L fuel if Victor flies through it. And it is possible for him to fly to every country from the first country.

Victor now is at the country whose number is 1, he wants to know the minimal amount of fuel for him to visit every country at least once and finally return to the first country.


Input
The first line of the input contains an integer T, denoting the number of test cases.
In every test case, there are two integers n and m in the first line, denoting the number of the countries and the number of the flights.

Then there are m lines, each line contains three integers ui, vi and wi, describing a flight.

1≤T≤20.

1≤n≤16.

1≤m≤100000.

1≤wi≤100.

1≤ui,vi≤n.


Output
Your program should print T lines : the i-th of these should contain a single integer, denoting the minimal amount of fuel for Victor to finish the travel.


Sample Input
1
3 2
1 2 2
1 3 3


Sample Output
10

题目大意:经过多年的努力,Victor终于考到了飞行驾照。为了庆祝这件事,他决定给自己买一架飞机然后环游世界。他会驾驶一架飞机沿着规定的航线飞行。在地球上一共有nn个国家,编号从11到nn,各个国家之间通过mm条双向航线连接,第ii条航线连接第u_iu
​i
​​ 个国家与第v_iv
​i
​​ 个国家,通过这条航线需要消耗w_iw
​i
​​ 升油,且从11号国家可以直接或间接到达22到nn中任意一个国家。

Victor一开始位于11号国家,他想知道从11号国家出发,经过各个国家至少一次并最后回到11号国家消耗的总油量的最小值是多少。

解题思路:
Floyd算法和状态dp

上代码:

/*
2015 - 8 - 29 中午
Author: ITAK

今日的我要超越昨日的我,明日的我要胜过今日的我,
以创作出更好的代码为目标,不断地超越自己。
*/
#include <cstdio>
#include <iostream>
using namespace std;
#define INF 1e9+7
const int sizet = (1<<16);
int d[16][16];
int dp[sizet][16];
int n,m;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; ++i)
            for(int j=0; j<n; ++j)
            {
                if(i == j) d[i][j] = 0;
                else d[i][j] = INF;
            }
        int u,v,w;
        for(int i=0; i<m; ++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            if(d[u-1][v-1] > w)
            {
                d[u-1][v-1] = w;
                d[v-1][u-1] = w;
            }
        }
        for(int k=0; k<n; k++)
            for(int i=0; i<n; i++)
                for(int j=0; j<n; j++)
                    d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
        for(int i=0; i<sizet; ++i)
            for(int j=0; j<n; ++j)
                dp[i][j] = INF;
        dp[1][0] = 0;
        for(int k=1; k<sizet; ++k)
            for(int i=0; i<n; ++i)
                for(int j=0; j<n; ++j)
                    dp[k|(1<<i)|(1<<j)][i] = min(dp[k|(1<<i)|(1<<j)][i],d[j][i]+dp[k|(1<<j)][j]);
        int minx=INF;
        int tt = (1<<n)-1;
        for(int i=0; i<n; i++)
            if(minx > dp[tt][i]+d[i][0])
                minx = dp[tt][i]+d[i][0];
        printf("%d\n",minx);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值