poj 3311 状态压缩 hdu 4284 TSP

POJ 3311 Hie with the Pie

题目链接:http://poj.org/problem?id=3311

//Floyd + 状态压缩DP
//题意是有N个城市(1~N)和一个PIZZA店(0),要求一条回路,从0出发,又回到0,而且距离最短
//也就是TSP(旅行商)问题,首先不难想到用FLOYD先求出任意2点的距离dis[i][j]
//接着枚举所有状态,用11位二进制表示10个城市和pizza店,1表示经过,0表示没有经过
//定义状态DP(S,i)表示在S状态下,到达城市I的最优值
//接着状态转移方程:DP(S,i) = min{DP(S^(1<<i-1),j) + dis[j][i],DP(S,i)},其中S^(1<<i-1)表示未到达城市i的所有状态,1<=j<=n
//对于全1的状态,即S = (1<<n)-1则表示经过所有城市的状态,最终还需要回到PIZZA店0


hdu 4284 Travel floyd + 状压DP


http://acm.hdu.edu.cn/showproblem.php?pid=4284

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<memory.h>
using namespace std;
const int inf=1<<29;
const int maxn=102;
int n,t,m,h,money,dp[1<<15][102],map[102][102];
struct node
{
    int id,ci,di;
} p[maxn];
void floyd()
{
    int i,j,k;
    for(k=1; k<=n; k++)
    {
        for(i=1; i<=n; i++)
        {
            if(map[i][k]!=inf)
                for(j=1; j<=n; j++)
                {
                    if(map[k][j]!=inf&&map[i][j]>map[i][k]+map[k][j])
                    {
                        map[i][j]=map[i][k]+map[k][j];
                    }
                }
        }
    }
}
void DP()
{
    int i,j,k;
    floyd();
    memset(dp,-1,sizeof(dp));
    for (i = 0; i < h; ++i)
    {
        int v = p[i].id;
        if (money - map[1][v] - p[i].di >= 0)
        {
            dp[1<<i][i] = money - map[1][v] - p[i].di + p[i].ci;
        }
    }
    for (i = 1; i <(1<<h); ++i)
    {
        for (j = 0; j < h; ++j)
        {
            if (dp[i][j] == -1) continue;//对于以j结尾的i路线存在
            int u = p[j].id;
            for (k = 0; k < h; ++k) //查看j是否可到k
            {
                if ((i&(1<<k)) == 0)
                {
                    int v = p[k].id;
                    if (dp[i][j] - map[u][v] - p[k].di >= 0) //可到
                    {
                        int now = (i^(1<<k));
                        if (dp[now][k] == -1 || dp[now][k] < dp[i][j] - map[u][v] - p[k].di + p[k].ci)
                            dp[now][k] = dp[i][j] - map[u][v] - p[k].di + p[k].ci;
                    }
                }
            }
        }
    }
}
int main()
{
    cin>>t;
    while(t--)
    {
        int i,j,k,a,b,c;
        cin>>n>>m>>money;
        for(i=0; i<=n; i++)
        {
            for(j=0; j<=n; j++)
            {
                if(i!=j) map[i][j]=inf;
                else map[i][j]=0;
            }
        }
        for(i=1; i<=m; i++)
        {
            cin>>a>>b>>c;
            if(map[a][b]>c)
            {
                map[a][b]=map[b][a]=c;
            }
        }
        cin>>h;
        for(i=0; i<h; i++)
        {
            cin>>p[i].id>>p[i].ci>>p[i].di;
        }
        DP();
        bool flag = false ;
        for (i =0; i <h; ++i)
        {
            if (dp[((1<<h) - 1)][i] - map[p[i].id][1]>=0)
            {
                flag = true;
                break;
            }
        }
        if (flag) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值