poj 3311 Hie with the Pie

  题意:有n个城市和一个披萨店(0),给出一个(n+1)阶的矩阵,表示 i 到 j 的距离,每个点可走多次。求从披萨店出发,再回到披萨店,把每个城市走一遍要走的最近距离。

  状态DP,状态s二进制中第几位表示第几个城市走没走过的状态,0表示每走过,1表示走过。

  先用Floyd求任意两点之间的最近距离,然后状态s从0开始到 (1<<n)-1,求dp[s][i],dp[s][i]表示状态s时,走到城市 i 时的最近距离。最后再求 (dp[(1<<n)-1][i]+map[i][0])的最小值。

#include<stdio.h>
#include<string.h>
#define min(a,b) (a)>(b)?(b):(a)

const int inf = 99999999;
int n;
int map[15][15];
int dp[1200][15];
void Input()
{
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            scanf("%d",&map[i][j]);
}
void Floyd()
{
    for(int k=0;k<=n;k++)
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                if(map[i][j]>map[i][k]+map[k][j])
                    map[i][j]=map[i][k]+map[k][j];
}
void Deal()
{
    for(int s=0;s<(1<<n);s++)
    {
        for(int i=1;i<=n;i++)
        {
            if(s & (1<<(i-1)))
            {
                if(s==(1<<(i-1))) dp[s][i]=map[0][i];
                else
                {
                    dp[s][i]=inf;
                    for(int j=1;j<=n;j++)
                        if(s & (1<<(j-1)) && j!=i)
                            dp[s][i]=min(dp[s][i],dp[s^(1<<(i-1))][j]+map[j][i]);
                }
            }
        }
    }
    int ans;
    int stat=(1<<n)-1;
    ans=dp[stat][1]+map[1][0];
    for(int i=2;i<=n;i++)
        ans=min(ans,dp[stat][i]+map[i][0]);
    printf("%d\n",ans);
}
int main()
{
    while(scanf("%d",&n) && n)
    {
        memset(dp,0,sizeof(dp));
        Input();
        Floyd();
        Deal();
    }
    return 0;
}
View Code

 

posted @ 2013-08-17 20:24  yongren1zu  阅读(146)  评论(0编辑  收藏  举报