题意:外卖员开始在0号节点,有N个人点了外卖,(N<=10),现在告诉两两间距离,问怎么配送,使得每个人的外卖都送外,然后回到0号点的总时间最短,注意,同一个点可以多次经过。
思路:TSP问题(货郎担问题),可以通过状态DP解决小数据问题。 先floyd求一下两两最近距离,然后DP;
dp[i][j]表示经过状态为i,当前在j号节点是最小耗时。 ans=min(dp[S][i]+dis[i][0]);
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=2400; int dp[maxn][20],dis[20][20],N,cnt,ans,S; int Laxt[maxn],Next[maxn],To[maxn],Len[maxn]; void floyd() { rep(k,0,N) rep(i,0,N) rep(j,0,N) if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j]; } void solve() { S=(1<<(N+1))-1; dp[1][0]=0; rep(i,1,S){ rep(k,0,N) rep(j,0,N){ dp[i|(1<<j)][j]=min(dp[i][k]+dis[k][j],dp[i|(1<<j)][j]); } } } int main() { while(~scanf("%d",&N)&&N){ memset(dp,38,sizeof(dp)); rep(i,0,N) Laxt[i]=0; cnt=0; rep(i,0,N) rep(j,0,N) scanf("%d",&dis[i][j]); floyd(); solve(); ans=dp[S][1]+dis[1][0]; rep(i,2,N) ans=min(ans,dp[S][i]+dis[i][0]); printf("%d ",ans); } return 0; }