1. 程式人生 > >【codevs2800】送外賣

【codevs2800】送外賣

題目描述 Description

有一個送外賣的,他手上有n份訂單,他要把n份東西,分別送達n個不同的客戶的手上。n個不同的客戶分別在1~n個編號的城市中。送外賣的從0號城市出發,然後n個城市都要走一次(一個城市可以走多次),最後還要回到0點(他的單位),請問最短時間是多少。現在已知任意兩個城市的直接通路的時間。

輸入描述 Input Description

第一行一個正整數n (1<=n<=15)

接下來是一個(n+1)*(n+1)的矩陣,矩陣中的數均為不超過10000的正整數。矩陣的i行j列表示第i-1號城市和j-1號城市之間直接通路的時間。當然城市a到城市b的直接通路時間和城市b到城市a的直接通路時間不一定相同,也就是說道路都是單向的。

輸出描述 Output Description

一個正整數表示最少花費的時間

樣例輸入 Sample Input

3 0 1 10 10 1 0 1 2 10 1 0 10 10 2 10 0

1

2

3

4

5

3

0 1 10 10

1 0 1 2

10 1 0 10

10 2 10 0

樣例輸出 Sample Output

8

資料範圍及提示 Data Size & Hint

1<=n<=15

解析:

       Floyd+狀壓DP。

程式碼;

#include <bits/stdc++.h>
using namespace std;

int n,m,ans=1e9;
int f[17][1<<16],d[17][17],ed;

int main()
{
	scanf("%d",&n);ed=(1<<(n+1))-1;
	for(int i=0;i<=n;i++)
	  for(int j=0;j<=n;j++) scanf("%d",&d[i][j]);
	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][k]+d[k][j],d[i][j]);
	memset(f,0x3f,sizeof(f));f[0][0]=0;
    for(int i=0;i<=ed;i++)
       for(int now=0;now<=n;now++)
           for(int from=0;from<=n;from++)
           {
			   if(((i|(1<<now))!=i))continue;
               f[now][i]=min(f[now][i],f[from][i^(1<<now)]+d[from][now]);
		   }
	cout<<f[0][ed];
	return 0;
}