1. 程式人生 > >codevs 2596 售貨員的難題

codevs 2596 售貨員的難題

input pan ++ name esp cstring fine 有一個 題解

題目描述 Description

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

輸入描述 Input Description

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

輸出描述 Output Description

最短的路程

樣例輸入 Sample Input

3

0 2 1

1 0 2

2 1 0

樣例輸出 Sample Output

3

題解:

傷心,記憶化搜索被洛谷卡了,不過在codevs上是ac的,設dp[i][j]表示處於i節點,經過了j這個集合中的元素的節點,還需要的最小花費,那麽轉移就很好轉移了,dp[i][j]=min(dp[i][j],dp[u][j|u]+mp[i][u])(u要不屬於集合j),就轉移到了u了,同時集合也就多了一個元素,所以j要 | 上j。從末狀態——dp[1][0],開始搜。結束就是到達了1並且全走了一遍——dp[1][1<<n-1]。

代碼:

#include<iostream>
#include<stdio.h>
#include
<algorithm> #include<cstring> #include<stdlib.h> #define inf 1<<30 using namespace std; int n; int dp[21][1<<21],mp[21][21]; bool b[21][1<<21]; int dfs(int now,int s){ if(b[now][s]) return dp[now][s]; if(now==1&&s==(1<<n)-1) return 0; int rest=inf;
for(int i=1;i<=n;i++){ if(s&(1<<(i-1))) continue; rest=min(rest,dfs(i,s|1<<(i-1))+mp[now][i]); } dp[now][s]=rest;b[now][s]=1; return rest; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>mp[i][j]; printf("%d",dfs(1,0)); }

codevs 2596 售貨員的難題