旅游景点 Tourist Attractions 题解


再次破了纪录,连做了3天。。。
让我们从头来一点一点分析
1.预处理
先看题面,乍一看貌似是个图论题,有n个点m条边,给定一些必须经过的点和强制经过顺序,求一条最短路
我们发现n和m都比较大,但是k很小只有20,于是考虑状压dp
仔细读题我们会发现,题目里有这么一句话:为了走最短路,可以路过一个城市但不停留
所以这里我们先求单源最短路,不要被n的20000吓到,由于状态转移只发生在20个城市之间,所以只需要处理他们之间的最短路,别的都是打酱油的
读入数据建图,分别跑1至k+1每个点到20个点以及终点的最短路,堆优化dij板子就行spfa已经死了,然后存到数组里
对于限制条件,依次读入记录就可以,我开始担心条件之间的关系,比如1在2前面,2在3前面,从而有1就在3前面,就跑了一个传递闭包(知识点蓝书p360),实际上不用,一会解释
2.dp
状压dp肯定有一维是状态,这里就是用20位的二进制数表示状态
我开始的方程是第一维表示已经过的点数,第二维状态,第三维停在的城市
就有 f[i][j][u]=min(f[i][j][u],f[i-1][l][p]+d[p][u])
第一维可以滚掉,但这样有些浪费空间,不是很优
考虑优化,我第一回把第三维去掉了,这样基本相当于时间换空间,而且处理点之间限制关系时很容易出错,wa了一天果然还是太菜了。。。
实际上第一维是没啥用的,因为第一维的东西本来就可以从状态中表示出来(1的个数),而停的城市很关键,因为这关乎后面的转移
重来,第一维表示停在的城市,第二维是状态,就有
f[i][j]=min(f[i][j],f[p][l]+d[p][i])
这里的l是j的子状态,并且要满足l是j的任意一位的1变成0(有且仅有1位)
所以个人认为枚举的时候直接用lowbit相关运算枚举所有合法状态比较好,直接枚举再判断合法的时候限制可能有点多比较乱明明是你代码能力不行
i就是j和l差的那个一的位置,比如j=11100100,l=10100100,i就是7
p是在l上的一个1,比如上面那个例子,p枚举的就是3,6,8
如果i必须在p前面,说明状态转移不合法,直接continue
觉得然后大概思路就有了然后就调了两天
3.各种坑
首先是起点终点问题,原状态是本来在1,要走k个城市,故要走1-k+1,而且最后要停在n号,等于是又多了一个城市
我把每个序号都-1了,这样f[0][0]就是在1号不动,但是这样预处理也要跟着变,注意别整乱了,不然出来正无穷直接怀疑人生(大佬请无视)
如果你开始枚举的状态转移无法从0转移到1,就要提前把只经过1个城市的状态预处理
为了节约时空,我的dp只处理到k+1,最后的n再枚举取最小值,事实证明这样避免了特判出错
还有是在状态转移的时候,枚举到l是要先判断合不合法,因为l的所有点都是已经到过的,必须保证所有的p属于l,都有i不在p之前经过
只要有一个p不合法,整个l就不合法,都不能要,而不是只舍去对应的p接着枚举其他
这个地方卡的时间最长,改完39--80+。。。
时间的话,能用一波位运算解决的问题就不要调用自己写的函数,保证循环内操作o1
还有就是memset,初始化正无穷,但0x3f会出玄学错误,1e9也是,96分就因为这。。。,memset50是个好东西(8亿多),省时间的话可以改成for循环
k==0特判直接输出1-n最短路
4.卡空间
这题洛谷上空间异常的死,容易mle,两种思路,滚动数组或卡常
貌似都要把状态预处理
先鸽着
奉上拙劣的代码

1 #include <bits/stdc++.h>
2 using namespace std;
3 struct node{
4 int from,to,v,next;
5 }a[400005];
6 int head[20005],mm=1;
7 inline void add(int x,int y,int z)
8 {
9 a[mm].from=x;a[mm].to=y;a[mm].v=z;
10 a[mm].next=head[x];head[x]=mm++;
11 }
12 int dis[20005];bool v[20005];
13 struct ttsc{
14 int c,d;
15 friend bool operator<(ttsc x,ttsc y)
16 {
17 return x.d>y.d;
18 }
19 };
20 priority_queue <ttsc> q;
21 inline void dj(int s)
22 {
23 memset(dis,0x3f,sizeof(dis));
24 memset(v,0,sizeof(v));
25 int x,y;ttsc cc;
26 cc.c=s,cc.d=0;
27 q.push(cc);
28 dis[s]=0;
29 while(!q.empty())
30 {
31 x=q.top().c;
32 y=q.top().d;
33 q.pop();
34 if(!v[x])
35 {
36 v[x]=1;
37 for(int i=head[x];i;i=a[i].next)
38 {
39 cc.c=a[i].to;
40 if(dis[cc.c]>y+a[i].v)
41 {
42 dis[cc.c]=y+a[i].v;
43 cc.d=dis[cc.c];
44 q.push(cc);
45 }
46 }
47 }
48 }
49 }
50 vector <int>state;
51 inline int lowbit(int x)
52 {
53 return x&(-x);
54 }
55 int dd[25][25];bool sb[25][25];int f[21][1100000];
56 int main()
57 {
58 int n,m,k,xz;
59 cin>>n>>m>>k;
60 for(int i=1;i<=m;i++)
61 {
62 int x,y,z;
63 scanf("%d%d%d",&x,&y,&z);
64 add(x,y,z);add(y,x,z);
65 }
66 for(int i=1;i<=k+1;i++)
67 {
68 dj(i);
69 for(int j=1;j<=k+1;j++)
70 dd[i-1][j-1]=dis[j];
71 dd[i-1][k+1]=dis[n];
72 }
73 cin>>xz;
74 for(int i=1;i<=xz;i++)
75 {
76 int x,y;
77 scanf("%d%d",&x,&y);
78 sb[x-1][y-1]=1;
79 }
80 if(k==0)
81 {
82 dj(1);
83 cout<<dis[n];
84 return 0;
85 }
86 // for(int i=0;i<=k+1;i++)sb[i][k+1]=1;这里如果枚举到k+1直接输出答案,就要有这句话
87
88 // for(int kk=0;kk<=k+1;kk++)
89 // for(int i=0;i<=k+1;i++)
90 // for(int j=0;j<=k+1;j++) 开始走的传递闭包,实际没用,因为不合法无法更新,
91 // sb[i][j]|=sb[i][kk]&sb[kk][j]; 如果加上,唯一好处就是一些不合法状态提前continue,也快不了多少
92 for(int i=0;i<=k;i++)
93 for(int j=0;j<=(1<<k)-1;j++)
94 f[i][j]=8e8;//不能太大 memset(f,50,sizeof(f))
95 int pmzg=1;
96 for(int i=1;i<=k+1;i++)
97 {
98 state.push_back(pmzg);
99 pmzg*=2;
100 }
101 for(int i=0;i<state.size();i++)f[i+1][state[i]]=dd[0][i+1];//预处理
102 f[0][0]=0;
103 for(int j=0;j<=(1<<(k))-1;j++)
104 {
105 for(int tem=j;tem;tem=(tem&(tem-1)))
106 {
107 int lt=lowbit(tem);
108 int u=log(lt)/log(2)+1;
109 int l=(j&(~lt));bool stop=0;
110 for(int p=1;p<=k;p++)//l是否合法
111 {
112 if(sb[u][p]&&((l>>(p-1))&1))
113 {stop=1;p=k;}
114 }
115 if(stop)continue;//舍去不合法状态
116 for(int p=1;p<=k;p++)
117 {
118 if(!((l>>(p-1))&1))continue;
119 f[u][j]=min(f[u][j],f[p][l]+dd[p][u]);
120 }
121 }
122 }
123 int ans=2147483600;
124 for(int i=1;i<=k;i++)
125 ans=min(ans,f[i][(1<<k)-1]+dd[i][k+1]);
126 cout<<ans;
127 return 0;
128 }
要有耐心一点点调,最后调出来的感觉真的不一样
执.
旅游景点 Tourist Attractions 题解的更多相关文章
- D. 旅游景点 Tourist Attractions 状压DP
题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD 不希望在刚吃过一顿大餐之后立刻去下一 ...
- csp-s模拟48,49 Tourist Attractions,养花,画作题解
题面:https://www.cnblogs.com/Juve/articles/11569010.html Tourist Attractions: 暴力当然是dfs四层 优化一下,固定两个点,答案 ...
- [Python爬虫] Selenium获取百度百科旅游景点的InfoBox消息盒
前面我讲述过如何通过BeautifulSoup获取维基百科的消息盒,同样可以通过Spider获取网站内容,最近学习了Selenium+Phantomjs后,准备利用它们获取百度百科的旅游景点消息盒(I ...
- bzoj [POI2007]旅游景点atr 状态压缩+Dij
[POI2007]旅游景点atr Time Limit: 30 Sec Memory Limit: 357 MBSubmit: 2258 Solved: 595[Submit][Status][D ...
- 【BZOJ1097】[POI2007]旅游景点atr 最短路+状压DP
[BZOJ1097][POI2007]旅游景点atr Description FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺 ...
- BZOJ1097: [POI2007]旅游景点atr
..k次最短路后,考虑如何满足先走一些点 用状压dp,每一个点考虑它所需要经过的点a[i],当当前走过的点包含a[i]时,i 这个点才可以到达. 写的时候用记忆化搜索. #include<bit ...
- 【BZOJ-1097】旅游景点atr SPFA + 状压DP
1097: [POI2007]旅游景点atr Time Limit: 30 Sec Memory Limit: 357 MBSubmit: 1531 Solved: 352[Submit][Sta ...
- BZOJ 1097: [POI2007]旅游景点atr( 最短路 + 状压dp )
先最短路预处理, 然后状压就行了 -------------------------------------------------------------------------- #include ...
- BZOJ_1097_[POI2007]旅游景点atr_状压DP
BZOJ_1097_[POI2007]旅游景点atr_状压DP 题面描述: FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣 的事情.经过这些城市的顺 ...
随机推荐
- 简单聊一下Uwsgi和Django的爱恨情仇
项目目录:/root/app Uwsgi的配置文件 [uwsgi] # Python扩展包安装的地方 pythonpath=/usr/local/src/python3/lib/python3.5/s ...
- NDT匹配: The Normal Distributions Transform: A New Approach to Laser Scan
介绍 大多数激光匹配算法都是基于点或者线的特征匹配,该论文提出一种2D激光扫描匹配算法,方法类似于占据栅格,将2D平面分为一个个cell,对于每个cell,设定其一个正态分布,表示该网格测量到每个点的 ...
- 跟我一起学Go系列:gRPC 全局数据传输和超时处理
gRPC 在多个 GoRoutine 之间传递数据使用的是 Go SDK 提供的 Context 包.关于 Context 的使用可以看我之前的一篇文章:Context 使用. 但是 Context ...
- Pytest单元测试框架之FixTure基本使用
前言: 在单元测试框架中,主要分为:测试固件,测试用例,测试套件,测试执行及测试报告: 测试固件不难理解,也就是我们在执行测试用例前需要做的动作和测试执行后的需要做的事情: 比如在UI自动化测试中,我 ...
- 10、Java——内部类
1.类中定义类 (1)当一类中的成员,作为另外一种事物的时候,这个成员就可以定义为内部类. (2)分类:①成员内部类 ②静态内部类 ③私有内部类 ④局部内部类 ⑤匿名内部类 ⑥Lambda表达式 ...
- 【开发工具】-- IDEA集成Git在实际项目中的运用
1.企业实际项目中Git的使用 在实际的企业项目开发中,我们一般Java的项目在公司都有自己的局域网代码仓库,仓库上存放着很多的项目.以我工作过的公司如华为的项目,一般是存放在企业内部的CodeHub ...
- 最大公约数and最小公倍数(Java版)
1.最大公约数and最小公倍数 import java.util.Scanner; public class MultipleAndDivisor { public static void main( ...
- Skywalking-02:如何写一个Skywalking trace插件
如何写一个Skywalking trace插件 javaagent 原理 美团技术团队-Java 动态调试技术原理及实践 类图 实现 ConsumeMessageConcurrentlyInstrum ...
- 1.4matlab矩阵的表示
1.4matlab矩阵的表示 矩阵的建立 利用直接输入法建立矩阵:将矩阵的元素用中括号括起来,按矩阵的顺序输入各元素,同一行的各元素之间用逗号或空格分隔,不同行的元素之间用分号分隔. 利用已建立好的矩 ...
- 深入刨析tomcat 之---第10篇 how tomcat works 第13章,Response 发送错误信息 sendError
writedby 张艳涛 在浏览器中发送一个错误应用url 那么tomcat是如何发送错误的呢? 基本上是发送http 的response协议,分为两部分一部分是response设置头信息, 那么先分 ...