题面在这里

再次破了纪录,连做了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 题解的更多相关文章

  1. D. 旅游景点 Tourist Attractions 状压DP

    题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD 不希望在刚吃过一顿大餐之后立刻去下一 ...

  2. csp-s模拟48,49 Tourist Attractions,养花,画作题解

    题面:https://www.cnblogs.com/Juve/articles/11569010.html Tourist Attractions: 暴力当然是dfs四层 优化一下,固定两个点,答案 ...

  3. [Python爬虫] Selenium获取百度百科旅游景点的InfoBox消息盒

    前面我讲述过如何通过BeautifulSoup获取维基百科的消息盒,同样可以通过Spider获取网站内容,最近学习了Selenium+Phantomjs后,准备利用它们获取百度百科的旅游景点消息盒(I ...

  4. bzoj [POI2007]旅游景点atr 状态压缩+Dij

    [POI2007]旅游景点atr Time Limit: 30 Sec  Memory Limit: 357 MBSubmit: 2258  Solved: 595[Submit][Status][D ...

  5. 【BZOJ1097】[POI2007]旅游景点atr 最短路+状压DP

    [BZOJ1097][POI2007]旅游景点atr Description FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺 ...

  6. BZOJ1097: [POI2007]旅游景点atr

    ..k次最短路后,考虑如何满足先走一些点 用状压dp,每一个点考虑它所需要经过的点a[i],当当前走过的点包含a[i]时,i 这个点才可以到达. 写的时候用记忆化搜索. #include<bit ...

  7. 【BZOJ-1097】旅游景点atr SPFA + 状压DP

    1097: [POI2007]旅游景点atr Time Limit: 30 Sec  Memory Limit: 357 MBSubmit: 1531  Solved: 352[Submit][Sta ...

  8. BZOJ 1097: [POI2007]旅游景点atr( 最短路 + 状压dp )

    先最短路预处理, 然后状压就行了 -------------------------------------------------------------------------- #include ...

  9. BZOJ_1097_[POI2007]旅游景点atr_状压DP

    BZOJ_1097_[POI2007]旅游景点atr_状压DP 题面描述: FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣 的事情.经过这些城市的顺 ...

随机推荐

  1. Acunetix与WAF集成:Acunetix和F5 BigIP ASM

    该的Acunetix API让您有机会来实现任务自动化,从而提高效率-尤其是当你可以用加速您的工作流程的其他组件的功能整合.在此示例中,我们将在上一篇文章的基础上,向您展示如何在Bash脚本中使用Ac ...

  2. Adaptive AUTOSAR 学习笔记 2 - 官方文档下载及阅读建议

    目前互联网上没有太多的 Adaptive AUTOSAR 的学习资料,官方文档是一个很不错的途径.看过官方文档才发现,目前很多关于 Adaptive AUTOSAR 的文章都是官方文档的简化翻译,不如 ...

  3. Vmware 恢复flat.vmdk和delta.vmdk

    背景: 一次客户现场突然掉电,导致虚拟机文件夹里面的文件丢失,只剩余-flat.vmdk和-delta.vmdk文件,其他文件全部丢失,文件格式原本为"文件"格式.新建虚拟机无法直 ...

  4. Django基础-001

    一.开发模式 MVC模式: model:数据库 view:前端展示 controller:逻辑控制MTV模式 model:数据库 view:逻辑控制 template:前端展示 二.Django介绍 ...

  5. 家庭账本开发day07

    返回数据问题解决,需要按照规定的json数据进行返回. 利用jsonobejact或者GSON工具将对象ArrayList转化为json 格式.然后response.getWriter().write ...

  6. Command 'ifconfig' not found, but can be installed with: sudo apt install net-tools VM Ubuntu 解决方案

    VMware下安装的Ubuntu 一开始由于Firefox连不上网,然后通过看了https://www.bbsmax.com/A/VGzlEGYJbq/这个文章之后,自己也测了一下,确实好用 但是if ...

  7. stream之forEach的用法

    public static class Student{ private String name; private String sex; private String age; public Str ...

  8. Map集合笔记

    一.Map集合的特点 Map集合是一个双列集合 Map中的元素,key和value的数据类型可以相同,也可以不同. Map中的元素,key是允许重复的,value是可以重复的 Map中的元素,key和 ...

  9. 手写Spring框架,是时候撸个AOP与Bean生命周期融合了!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 嘎小子,这片代码水太深你把握不住! 在电视剧<楚汉传奇>中有这么一段刘邦 ...

  10. 【经典结构】单例模式Singleton

    单例模式Singleton 1.含义 单例模式:即一个类只能创建一个实例. 只有一个实例 --> 不可以从类外new对象 --> 构造器私有化private --> 从类里创建实例: ...