Hie with the Pie

Hie with the Pie poj-3311

    题目大意:n+1个点,伪旅行商问题。

    注释:n<=10。

      想法:咳咳,第一道状压dp,下面我来介绍一下状压dp。

        所谓dp,就是动态性决策规划,通过上一时刻或上几时刻的状态来更新当前状态并且无后效性。而状压dp就是将之前的状态通过二进制表现出来。几个例子。有五个格子_ _ _ _ _。上面可以放棋子或者不放。我们将放棋子的格子标注为1,不放棋子的格子标注为0。那么,我们就可以用一个二进制数来表达出人任何一个的完整状态而不是片面的,这就是状压dp。但是由于我们需要表示出所有的状态,所以状压dp的空间复杂度是指数级的,这就比较的伤心。所以看见题目的数据范围有那么一个小的可怜的,可以考虑考虑状压dp。状压dp前置知识点是位运算,在此不做介绍。

      关于这道题,我们设dp[s][i]。表示s这个状态的最小代价,且这个状态最后到达的点是i。之后转移就是枚举s的上一个到达的点。在此,我们要注意,题目中给出的是邻接矩阵的形式,我们先用floyd求出两点之间的最短路,之后通过上一个到达的点的状态加上dis[j][i]来更新当前状态。

    最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#define inf 0x3f3f3f3f
using namespace std;
int dp[5000][20];
int map[20][20];
int main()
{
    int n;
    while(1)
    {
        memset(map,0x3f,sizeof(map));
        memset(dp,0,sizeof(dp));
        scanf("%d",&n);
        if(!n) return 0;
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=n;j++)
            {
                scanf("%d",&map[i][j]);
            }
        }
        for(int k=0;k<=n;k++)//floyd
        {
            for(int i=0;i<=n;i++)
            {
                for(int j=0;j<=n;j++)
                {
                    map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
                }
            }
        }
        for(int S=0;S<=(1<<n)-1;S++)//枚举所有状态
        {
            for(int i=1;i<=n;i++)//考虑最后到达的点
            {
                if(S&(1<<(i-1)))//现判断i是不是s中已经到达的点
                {    
                    if(S==(1<<(i-1)))//特判,如果s只到达过i
                    {
                        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^(1<<(i-1))][j]+map[j][i],dp[S][i]);
                            }
                        }
                    }
                }
            }
        }
        int ans=inf;
        for(int i=1;i<=n;i++)//最后所有的点全部都到达后,枚举最后到达的点去统计答案。
        {
            ans=min(ans,dp[(1<<n)-1][i]+map[i][0]);
        }
        printf("%d\n",ans);
    }
}

 

  小结:题目中明确指出所给的邻接矩阵可能不是对称的,容易在floyd时将其按照对称处理。

转载于:https://www.cnblogs.com/ShuraK/p/8468050.html

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值