【上海交大oj】邮递员小F(状态压缩dp)(旅行商问题)

1088. 邮递员小F

Description

因为制造类专业很难在大城市立足,曾经立志振兴中华之工业的小F,果断在本科毕业后转行做了一名光荣的邮递员。

他的任务是每天从总局出发,行走于所管辖区域的若干的邮局,收集所有的信,然后再汇总返回总局。

因为工作繁忙,同一个邮局他每天只希望去一次。

来往于任意两个邮局是有一定代价的。而且为了方便统计,假定来回两条道路上的代价假设是一样的。

现在小F希望你能给出他每天的最优行走方案,使得总的代价最少。

Input Format

输入数据包括两部分。

第一行为邮局数N。

接下来的N行为一个N×N的对称矩阵。矩阵的第i行,第j列元素Aij代表从邮局i到邮局j的消耗的代价。

规定总局的标号为1。

1≤N≤15

0≤Aij≤2000

Output Format

共一行,为满足题目要求的最小的代价。

Sample Input

4
0 6 7 9
6 0 6 5
7 6 0 8
9 5 8 0

Sample Output

26

其实就是旅行商问题,用动态规划解决。状态是当前所处的城市位置及已经走过的城市,达到当前状态的路径包括所有已经走过的城市(除了当前城市),需要记录的数据是走过这些城市并且从当前城市回到出发点所需的代价,那么最终需要得到的就是处在n个城市并且走过所有城市的代价中的最小值。保存当前所在城市需要一维数组,但保存走过的城市比较麻烦。由于每个城市都有两种状态(走过没走过),开数组保存就需要一个n维的数组,空间上肯定是不允许的,由于只有两种状态,故可用状态压缩成一个二进制的数来保存走过哪些城市。具体实现的时候我是用的递归的方法,因为递归比较好理解,不过动态规划一般来说都是用迭代的方法来实现,因为递归调用需要一些时间。不过对于本题,迭代实现会比较麻烦,因为状态比较多,只有一个城市时很好枚举,但当城市数多于3个时,枚举的情况就比较多,可以进行一些预处理,比如把i个城市时的所有状态先保存起来,这样就可以避免写太多的循环。以下是代码:

 1 #include <iostream>
 2 #include <cmath>
 3 using namespace std;
 4
 5 int cost[15][15];    //城市间的开销
 6 int dp[15][32768];  //动归的状态
 7 int N;
 8 int get_num_of1(int state) //计算一个整数的二进制中有多少个1,相当于状态中走过的城市个数
 9 {
10     int c = 0;
11     while (state)
12     {
13         state = state&(state-1);
14         c++;
15     }
16     return c;
17 }
18 int getc(int cur,int state)  //递归的过程
19 {
20     if (dp[cur][state] > -1) return dp[cur][state];
21     //state = ;  //去掉当前位
22     if (get_num_of1(state) == 2) return dp[cur][state] = cost[cur][0];  //没有其他点要经过了
23     int t = 2; //不算出发点
24     int mini = 3000000;
25     int tem;
26     for (int i = 1;i < N;++i,t<<=1)
27     {
28         if (i==cur) continue;
29         if (state & t)  //当前城市走过
30         {
31             tem = getc(i,state & (~(1<<cur))) + cost[i][cur]; //拿掉当前位
32             if (tem < mini) mini = tem;
33         }
34     }
35     return dp[cur][state] = mini;
36 }
37
38 int main(){
39     cin>>N;
40
41     for (int i = 0;i < N;++i) for (int j = 0;j < N;++j) cin>>cost[i][j];
42     int num = pow(2,N);
43     if (N==1)
44     {
45         cout<<0;
46         return 0;
47     }
48     for (int i = 0;i < N;++i) for (int j= 0;j < pow(2,N);++j) dp[i][j] = -1; //初始化
49     dp[0][1] = 0;
50     int mini = 3000000;
51     for (int i = 1;i < N;++i)  //从第i个城市返回出发点
52     {
53         int tem = cost[0][i] + getc(i,num-1);/
54         if (tem < mini) mini = tem;
55     }
56     cout<<mini;
57
58     return 0;
59 }

时间: 2024-08-19 05:46:41

【上海交大oj】邮递员小F(状态压缩dp)(旅行商问题)的相关文章

Light OJ 1406 Assassin`s Creed 状态压缩DP+强连通缩点+最小路径覆盖

题目来源:Light OJ 1406 Assassin`s Creed 题意:有向图 派出最少的人经过全部的城市 而且每一个人不能走别人走过的地方 思路:最少的的人能够走全然图 明显是最小路径覆盖问题 这里可能有环 所以要缩点 可是看例子又发现 一个强连通分量可能要拆分 n最大才15 所以就状态压缩 将全图分成一个个子状态 每一个子状态缩点 求最小路径覆盖 这样就攻克了一个强连通分量拆分的问题 最后状态压缩DP求解最优值 #include <cstdio> #include <cstri

Light OJ 1316 A Wedding Party 最短路+状态压缩DP

题目来源:Light OJ 1316 1316 - A Wedding Party 题意:和HDU 4284 差不多 有一些商店 从起点到终点在走过尽量多商店的情况下求最短路 思路:首先预处理每两点之前的最短路 然后只考虑那些商店 个数小于15嘛 就是TSP问题 状态压缩DP搞一下 状态压缩姿势不对 有必要加强 #include <cstdio> #include <algorithm> #include <queue> #include <vector>

西安邀请赛J题 状态压缩DP

Cacti是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具.Cacti是通过 snmpget来获取数据,使用 RRDtool绘画图形,而且你完全可以不需要了解RRDtool复杂的参数.它提供了非常强大的数据和用户管理功能,可以指定每一个用户能查看树状结构.host以及任何一张图,还可以与LDAP结合进行用户验证,同时也能自己增加模板,功能非常强大完善.界面友好.软件 Cacti 的发展是基于让 RRDTool 使用者更方便使用该软件,除了基本的 Snmp 流量

hdu 4917Permutation(状态压缩DP)

hdu 4917Permutation(状态压缩DP) 题意:将1~n的n个数排列成序列(n<=40),但有m(m<=20)个限制条件,其中第i个限制条件的表示为ai,bi.表示该序列的第ai的数要小于第bi的.问有多少中排列?保证有解 解法:我们首先可以明确一点,这m个限制条件,所表示的关系会构成若干个DAG(有向无环图,我将其称之为拓扑图).我们只要将这n个数,填入到拓扑图上,使其满足拓扑关系,那么这样的序列就是可以的.而这若干个拓扑图之间,是不会相互影响的,因而我们可以单独考虑每一个拓扑

[知识点]状态压缩DP

// 此博文为迁移而来,写于2015年7月15日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w6jf.html 1.前言 动态规划,永远的痛. 好了不扯远了.状态压缩动态规划,其实看名字还是较好理解的.我们在动态规划的时候,最重要的就在于状态的设计和状态转移方程.那么,如果当我们状态过多导致时间或空间不够的饿时候,就可以用到状态压缩.王队(@wyh2000)说状态压缩DP难起来的话会很难,但是今天我们只讲最最最基础

【HDU2825】Wireless Password【AC自动机,状态压缩DP】

题意 题目给出m(m<=10)个单词,每个单词的长度不超过10且仅由小写字母组成,给出一个正整数n(n<=25)和正整数k,问有多少方法可以组成长度为n的文本且最少包含k个给出的单词. 分析 和上一个AC自动机很相似,上一篇博客是不包含任何一个单词长度为n的方案数,这个题是包含至少k个单词的方案数,而且n,m,k都非常的小. 按照前面的经验很容易想到,我们还是得先建一个AC自动机,然后把它的单词结点标记出来.与前面不同的是我们在状态转移的时候需要考虑到当前走过的结点已经包含多少单词了.所以我们

# 奇怪的道路 状态压缩DP

奇怪的道路 状态压缩DP 问题: 小宇从历史书上了解到一个古老的文明.这个文明在各个方面高度发达,交通方面也不例外. 考古学家已经知道,这个文明在全盛时期有\(n\)座城市,编号为\(1..n\).\(m\)条道路连接在这些城市之间,每条道路将两个城市连接起来,使得两地的居民可以方便地来往.一对城市之间可能存在多条道路. 据史料记载,这个文明的交通网络满足两个奇怪的特征.首先,这个文明崇拜数字K,所以对于任何一条道路,设它连接的两个城市分别为\(u\)和\(v\),则必定满足\(1 <=|u -

HDU--1074(状态压缩DP)

典型的状态压缩DP,给出了每件作业的截止时间和花费,求让老师扣分最少的写作业方式.把完成n种作业用状态2^n-1表示,dp[s]表示 完成状态s时,最小扣分.比如“111”,那么可以由“011”,“110”,“101”转移过来,分别表示选了0,1号作业,1,2号作业,0,2号作业. t[s]表示状态S记录的总时间.dp[s] = min{dp[j]+c[k] - d[k]},其中j = i^(1<<k),0<k<n;pre[s]表示状态s完成时,最末尾完成的作业, #include

poj 2411 Mondriaan&#39;s Dream(状态压缩+dp)

 题意:用1*2砖块铺满n*m的房间. 思路转自:http://www.cnblogs.com/scau20110726/archive/2013/03/14/2960448.html 因为这道题输入范围在11*11之间,所以可以先打表直接输出.......... 状态压缩DP 经典覆盖问题,输入n和m表示一个n*m的矩形,用1*2的方块进行覆盖,不能重叠,不能越出矩形边界,问完全覆盖完整个矩形有多少种不同的方案 其中n和m均为奇数的话,矩形面积就是奇数,可知是不可能完全覆盖的.接着我们来看