1. 程式人生 > >luogu P1171 售貨員的難題

luogu P1171 售貨員的難題

name 代碼 true span turn str %d 說明 -s

題目背景

數據有更改

題目描述

某鄉有n個村莊(1<n<20),有一個售貨員,他要到各個村莊去售貨,各村莊之間的路程s(0<s<1000)是已知的,且A村到B村與B村到A村的路大多不同。為了提高效率,他從商店出發到每個村莊一次,然後返回商店所在的村,假設商店所在的村莊為1,他不知道選擇什麽樣的路線才能使所走的路程最短。請你幫他選擇一條最短的路。

輸入輸出格式

輸入格式:

村莊數n和各村之間的路程(均是整數)。

輸出格式:

最短的路程。

輸入輸出樣例

輸入樣例#1:
3
0 2 1
1 0 2
2 1 0
輸出樣例#1:
3

說明

輸入解釋

3 {村莊數}

0 2 1 {村莊1到各村的路程}

1 0 2 {村莊2到各村的路程}

2 1 0 {村莊3到各村的路程}

題目鏈接:https://www.luogu.org/problem/show?pid=1171#sub

解題報告

傻逼狀壓DP,沒了!!!

AC代碼

#include<cstdio> 
#include<iostream>
#include<vector>
#include<algorithm>
#define INF (1<<28)
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using namespace std;
int f[1<<20][20];
int one[20];
int zero[20];
int r[21][21];
int n,ans,m,o,z; 
inline int min(int x,int y){
	return x<y?x:y;
}
int main(){
	scanf("%d",&n);
	FOR(i,0,n-1)
		FOR(j,0,n-1)
			scanf("%d",&r[i][j]);
	m=(1<<n)-1;
	FOR(i,0,m)
		FOR(j,0,n-1)
			f[i][j]=INF;
	f[1][0]=0;
	for(register int i=1;i<=m;i+=2){
		one[0]=zero[0]=0;
		FOR(j,0,n-1)
			i&(1<<j)?one[++one[0]]=j:zero[++zero[0]]=j;
		FOR(k,1,one[0])
			FOR(j,1,zero[0]){
				o=one[k];
				z=zero[j];
				f[i|(1<<z)][z]=min(f[i|(1<<z)][z],f[i][o]+r[o][z]);
			}
	}
	ans=INF;
	FOR(i,1,n-1)
		ans=min(ans,f[m][i]+r[i][0]);
	cout<<ans<<endl;
	return 0;
}

  

luogu P1171 售貨員的難題