Live2d Test Env

Gym-100648B: Hie with the Pie(状态DP)

题意:外卖员开始在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\n",ans);
    }
    return 0;
}

 

posted @ 2019-07-18 09:28  nimphy  阅读(168)  评论(0编辑  收藏  举报