hdu3001(状压dp,三进制)
Travelling
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5896 Accepted Submission(s): 1908
1 2 100
3 2
1 2 40
2 3 50
3 3
1 2 3
1 3 4
2 3 10
90
7
以下文字转载于https://www.cnblogs.com/martinue/p/5490432.html
这题的状态压缩不是二进制了,换到了三进制!!
这是为何??
题目中明确的说了每个点最多走2次,也就是说压缩为二进制并不能直接求出结果了,因为二进制只能代表一个点是否被走过的状态,而具体走过了几次却并不能记录!!然而我们题目要求可以走两次呀!怎么办?!大牛们想到了办法,压缩为三进制!
将状态压缩为三进制之后,那么显然,我们的状态数增多了,那么这些增加的状态数代表着什么呢?
举个栗子:将46化为3进制之后是1201,那么我们就可以暴力的来表示第1个点去过1次,第2个点没去过,第3个点去过2次,第4个点也去过1次!
用上面这个例子来说明一个问题,就是我们用三进制来压缩了题目要求的所有的状态,因为每个数位可以是2了,这个2是有意义的!就是表示某个点是否去过2次!
然后dp部分是状态压缩的常规解法,主要在于理解为何要化为3进制的状态压缩。
#include<stdio.h>
#include<string.h>
#define Max 0x3fffffff
int dp[60000][12];//记录dp[i][j]当第i种情况时以j地点为结束地点的总路程,例:46=(1201)3;则dp[46][0](i=46,j=0)代表当1走1次,2走0次,3走2次,4走1次时最后以1为终点所走路程。
int num[12];//记录3的几次方{1,3,9。。。。59049(3的10次方)}
int mp[12][12];//记录a到b的路程
int dight[60000][12];//记录第i中种情况j号位走了多少次j=(0---->n-1)
int min(int a,int b)
{
return (a>b)?b:a;
}
int init()//初始化所需条件
{
int i,j;
int a;
num[0]=1;
for(i=1;i<=10;i++)
num[i]=num[i-1]*3;
for(i=0;i<num[10];i++)
{
a=i;
for(j=0;a!=0;j++)
{
dight[i][j]=a%3;
a=a/3;
//printf("%d",dight[i][j]);
}
//printf("\n");
}
return 0;
}
int main()
{
int n,m;
int i,j,k;
int a,b,c;
int flag;
int mx;
init();
while(scanf("%d%d",&n,&m)!=EOF)
{
` mx=Max;
for(i=0;i<num[n];i++)//初始化第i种情况以j为终点的路程
{
for(j=0;j<n;j++)
dp[i][j]=Max;
}
for(i=0;i<n;i++)
{
dp[num[i]][i]=0;//初始化起点,因为num[i][i]转换为3进制时就等于只有i号为走了一次的情况 ,而它又以i为终点,所以这就是以i号为起点的情况
mp[i][i]=0;
for(j=0;j<i;j++)
mp[i][j]=mp[j][i]=Max;
}
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
mp[a-1][b-1]=mp[b-1][a-1]=min(mp[a-1][b-1],c);//我们是从0-->n-1的,记得减一
}
for(i=0;i<num[n];i++)
{
flag=1;
for(j=0;j<n;j++)
{
if(dight[i][j]==0)//记录是否每个位置都到过
flag=0;
if(dp[i][j]!=Max)//当第i种情况时以j为终点有一段路程可以满足的这个条件时
{
for(k=0;k<n;k++)//因为dp[i][j]这种情况存在,所以可以更新dp[i+num[k]][k]的这种情况,i+num[k]相当于在i这种情况下在k号位置加一,然后就以k为终点。
{
if(dight[i][k]<=1&&j!=k&&mp[j][k]!=Max)//判断满足条件,由题意可知,k号位置经历的次数不能超过两次,所以dight[i][k]<=1,并且要有路从j到k。
{
int nt=i+num[k];//当第i种情况时k号位加一的情况
dp[nt][k]=min(dp[nt][k],dp[i][j]+mp[j][k]);//更新
}
}
}
}
if(flag==1)
{
for(j=0;j<n;j++)
mx=min(mx,dp[i][j]);//更新最短路程
}
}
if(mx==Max)
printf("-1\n");
else
printf("%d\n",mx);
}
return 0;
}
hdu3001(状压dp,三进制)的更多相关文章
- Travelling(HDU3001+状压dp+三进制+最短路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题目: 题意:n个城市,m条边,每条边都有一个权值,问你经过所有的城市且每条边通过次数不超过两次 ...
- HDU3001 Traveling (状压dp+三进制+Tsp问题总结)
(1)这道题最多可以走两次,所以有0, 1, 2三种状态,所以我们要用三进制 如果要用三进制,就要自己初始化两个数组, 一个是3的n次方,一个是三进制数的第几位的数字是什么 void init() { ...
- HDU - 3001 Travelling 状压dp + 三进制 [kuangbin带你飞]专题二
终于刷完搜索专题了. 题意:给定n个城市,每个城市参观不能超过两次,两个城市之间有道路通过需要花费X,求通过能所有城市的最小花费. 思路:每个城市有三个状态0,1,2,可用三进制存储所有城市的访问状态 ...
- POJ1185 状压dp(二进制//三进制)解法
很显然这是一道状压dp的题目 由于每个最优子结构和前两行有关,一个显而易见的想法是用三维dp[i][j][k]用来记录在第i行下为j状态,i - 1行为k状态时的最大值,然而dp[100][1 < ...
- hdu 3001 Travelling 经过所有点(最多两次)的最短路径 三进制状压dp
题目链接 题意 给定一个\(N\)个点的无向图,求从任意一个点出发,经过所有点的最短路径长度(每个点至多可以经过两次). 思路 状态表示.转移及大体思路 与 poj 3311 Hie with the ...
- HDU 3001 Travelling (状压DP,3进制)
题意: 给出n<=10个点,有m条边的无向图.问:可以从任意点出发,至多经过同一个点2次,遍历所有点的最小费用? 思路: 本题就是要卡你的内存,由于至多可经过同一个点2次,所以只能用3进制来表示 ...
- 『数 变进制状压dp』
数 Description 给定正整数n,m,问有多少个正整数满足: (1) 不含前导0: (2) 是m的倍数: (3) 可以通过重排列各个数位得到n. \(n\leq10^{20},m\leq100 ...
- 状压dp-----三进制
三进制的状压dp要先预处理3^n以及每一个数的每一位 例题 hdu3001 题意: 给定n 个城市已经 m 条路 以及对应路费 c,要求遍历所有城市最少的路费,每个城市不能超过2次. 题解: 看代码吧 ...
- poj1038 Bugs Integrated,Inc. (状压dp)
题意:N*M的矩阵,矩阵中有一些坏格子,要在好格子里铺2*3或3*2的地砖,问最多能铺多少个. 我的方法好像和网上流传的方法不太一样...不管了.... 由数据范围很容易想到状压dp 我们设某个状态的 ...
- 2018.10.05 NOIP模拟 上升序列(状压dp)
传送门 状压dp好题. 首先需要回忆O(nlogn)O(nlog n)O(nlogn)求lislislis的方法,我们会维护一个单调递增的ddd数组. 可以设计状态f(s1,s2)f(s1,s2)f( ...
随机推荐
- java.lang.NoClassDefFoundError: org/springframework/web/context/WebApplicationContext
一.NoClassDefFoundError与ClassNotFoundException NoClassDefFoundError错误的发生,是因为Java虚拟机在编译时能找到合适的类,而在运行时不 ...
- 使用AutoCloseable 实现自动关闭资源
一.认识AutoCloseable AutoCloseable接口位于java.lang包下,从JDK1.7开始引入. 1.在1.7之前,我们通过try{} finally{} 在finally中释放 ...
- MySQL补充
1.mysql限制显示条目数:Limit, offset 图片网址:https://sqlbolt.com/lesson/filtering_sorting_query_results 实例: SEL ...
- Python操作excel的几种方式--xlrd、xlwt、openpyxl
openpyxl xlrd xlwt 在处理excel数据时发现了xlwt的局限性–不能写入超过65535行.256列的数据(因为它只支持Excel 2003及之前的版本,在这些版本的Excel中 ...
- C# 有哪些集合
队列[Queue] //队列:先进先出 /* *增加元素到队列结尾处 *移除队列开始处 */ Queue queue=new Queue(); queue.Enqueue(Object); queue ...
- function_exists
在已经定义的函数列表(包括系统自带的函数和用户自定义的函数)中查找 function_name. 如果 function_name 存在且的确是一个函数就返回 TRUE ,反之则返回 FALSE .
- 海康摄像头配置固定IP
前言 首先要海康设备连接好网线,电脑客户端跟海康设备在同一个局域网络. 1.直接在海康网站下载SADP工具软件,安装SADP工具,如图所示: 2.安装成功后,桌面的出现设备网络搜索, 面板介绍:这里将 ...
- 『Python』setup.py简介
setup.py应用场合 网上见到其他人这样介绍: 假如我在本机开发一个程序,需要用到python的redis.mysql模块以及自己编写的redis_run.py模块.我怎么实现在服务器上去发布该系 ...
- 第三周学习进度条+PSP0过程文档
第三周学习进度条 第三周 所花时间(包括上课) 14:30-15:35(65)+19:00-21:20(140)+17:52-19:00(68)+19:10-20:45(95)+21:00-22 ...
- tomcat8.5 优化
第一步:配置user登录tomcat 参考:https://www.cnblogs.com/kevincaptain/p/10370794.html 第二步:性能优化 2.1tomcat的运行模式有3 ...