题目描述

小熊的地图上有n 个点,其中编号为1 的是它的家、编号为2, 3, . . . , n 的都是景点。部分点对之间有双向直达的公交线路。如果点x 与z1、z1 与z2、……、zk−1 与zk、zk 与y 之间均有直达的线路,那么我们称x 与y 之间的行程可转车k 次通达;特别地,如果点x 与y 之间有直达的线路,则称可转车0 次通达。

很快就要放假了,小熊计划从家出发去 4 个不. 同. 的景点游玩,完成 5 段行程后回家:家→ 景点A → 景点B → 景点C → 景点D → 家且每段行程最多转车k 次。转车时经过的点没有任何限制,既可以是家、也可以是景点,还可以重复经过相同的点。例如,在景点A → 景点B 的这段行程中,转车时经过的点可以是家、也可以是景点C,还可以是景点D → 家这段行程转车时经过的点。

假设每个景点都有一个分数,请帮小熊规划一个行程,使得小熊访问的四个不同景点的分数之和最大。

测试样例:

holiday.zip

输入输出格式

输入格式:

从文件holiday.in 中读入数据。
第一行包含3 个正整数n, m, k,分别表示地图上点的个数、双向直达的点对数量、每段行程最多的转车次数。
第二行包含n − 1 个正整数,分别表示编号为2, 3, . . . , n 的景点的分数。
接下来m 行,每行包含两个正整数x, y,表示点x 和y 之间有道路直接相连,保证1 ≤ x, y ≤ n,且没有重边,自环。

输出格式:

输出到文件holiday.out 中。
输出一个正整数,表示小熊经过的4 个不同景点的分数之和的最大值。

输入输出样例

输入样例#1:

【输入样例1】
8 8 1
9 7 1 8 2 3 6
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 1

【输入样例2】
7 9 0
1 1 1 2 3 4
1 2
2 3
3 4
1 5
1 6
1 7
5 4
6 4
7 4

输出样例#1:

【输出样例1】

27

【输出样例2】

7

【样例1 解释】
当计划的行程为1 → 2 → 3 → 5 → 7 → 1 时,4 个景点的分数之和为9+7+8+3 = 27,可以证明其为最大值。
行程1 → 3 → 5 → 7 → 8 → 1 的景点分数之和为24、行程1 → 3 → 2 → 8 → 7→ 1 的景点分数之和为25。它们都符合要求,但分数之和不是最大的。
行程1 → 2 → 3 → 5 → 8 → 1 的景点分数之和为30,但其中5 → 8 至少需要转车2 次,因此不符合最多转车k = 1 次的要求。
行程1 → 2 → 3 → 2 → 3 → 1 的景点分数之和为32,但游玩的并非4 个不同的景点,因此也不符合要求

当时考时脑子一塌糊涂,居然敢用搜索,爆搜的,没带剪枝,指数级......

0分:Game over!

题目分析

这道题乍看起来很复杂,其实我们可以把它抽象成两个部分:

题目原话:

每段行程最多转车k 次。转车时经过的点没有任何限制,既可以是家、也可以是景点,还可以重复经过相同的点。例如,在景点A → 景点B 的这段行程中,转车时经过的点可以是家、也可以是景点C,还可以是景点D → 家这段行程转车时经过的点。

所以,转车基本不会对后续操作产生影响,因为“转哪都无所谓”,但要求次数少于k次,因此,转多了的就不用管,只需考虑从i点到j点转车次数最少的方法,即最短路!

由于要求任意两点的最短路,首先可以想到Floyed算法,但n<=2500的数据范围让人不堪忍受。由于边权为1,可以采用广度优先算法实现:

1.广搜求最短路

其中:

add_edge(x,y)表示连由i到j的边,采用链式前向星实现。

step[j]表示队列第j个数到当前源点的距离。

vis[i]表示是否访问过点i.

    for(int i=1;i<=m;i++){int x,y;cin>>x>>y;add_edge(x,y);add_edge(y,x);}for(int i=1;i<=n;i++){memset(step,0,sizeof(step));memset(vis,0,sizeof(vis));memset(que,0,sizeof(que));que[1]=i;vis[i]=1;int hea=0,tail=1;while(hea<tail){hea++;int u=que[hea];int sat=step[hea];d[i][u]=sat;if(d[i][u]-1>kk) d[i][u]=d[0][0];for(int j=head[u];j!=-1;j=edge[j].next){int v=edge[j].to;if(vis[v]==0){step[++tail]=step[hea]+1;que[tail]=v;vis[v]=1;}}}} 

时间复杂度:O(n^2)

第二部分,对于任意点i(i>1)有4种可能:

1.点i之前已经旅游过0个点

2.点i之前已经旅游过1个点

3.2个点

4.3个点

设dp[i][j]表示点i在第j种可能下能得到的最大分数。

则有dp[i][1]=点i的分数(d[1][i]>0&&d[1][i]<=2502)

dp[i][2]=max{dp[j][1]}+点i的分数(下称val[i])(d[i][j]>0&&d[i][j]<=2502)

dp[i][k]=max(dp[j][k-1]}+val[i] (d[i][j]>0&&d[i][j]<=2502)

最后找最大且能走到点1的d[i][4],输出。

可是,行程1 → 2 → 3 → 2 → 3 → 1 的景点分数之和为32,但游玩的并非4 个不同的景点,因此也不符合要求!因此,设vis2[i][k][j]表示点i在上文中第k种情况下j是否走过,设q[i][k][(1~4)]表示点i在上文中第k种情况下走过的所有点:

 for(int i=2;i<=n;i++){if(d[1][i]<3000&&d[1][i]>=0){dp[i][1]=val[i];vis2[i][1][i]=1;q[i][1][1]=i;}}

初始化。

    for(int k=2;k<=4;k++){for(int i=2;i<=n;i++){int tmp=0;for(int j=2;j<=n;j++){if(d[i][j]==d[0][0]||i==j||d[i][j]<0) continue;if(vis2[j][k-1][i]==1) continue;if(dp[j][k-1]!=dp[0][0]){if(dp[j][k-1]>dp[i][k]){dp[i][k]=dp[j][k-1];tmp=j;}}}for(int j=1;j<=n;j++){q[i][k][j]=q[tmp][k-1][j];vis2[i][k][q[i][k][j]]=1;if(q[i][k][j]==0){q[i][k][j]=i;vis2[i][k][i]=1;break;}}dp[i][k]+=val[i];}}

动态规划。

    for(int i=2;i<=n;i++){if(d[i][1]>0&&d[i][1]<3000){maxn=max(maxn,dp[i][4]);}}cout<<maxn;

找最大值并输出。

完整:

#include<bits/stdc++.h>
using namespace std;
int n,m,kk,maxn=-1;
int d[2501][2501],cnt,dp[2501][4],vis2[2501][6][2501],q[2501][6][6];
int val[2501],vis[2501],head[2501],step[2501];
int que[2501];
struct Edge{int next;int to;int w;
}edge[30001];
void add_edge(int u,int v)
{cnt++;edge[cnt].to=v;edge[cnt].w=1;edge[cnt].next=head[u];head[u]=cnt;
}
int main()
{memset(d,0x3f,sizeof(d));memset(dp,-0x3f,sizeof(dp));memset(head,-1,sizeof(head));cin>>n>>m>>kk;for(int i=2;i<=n;i++){cin>>val[i];d[i][i]=0;}for(int i=1;i<=m;i++){int x,y;cin>>x>>y;add_edge(x,y);add_edge(y,x);}for(int i=1;i<=n;i++){memset(step,0,sizeof(step));memset(vis,0,sizeof(vis));memset(que,0,sizeof(que));que[1]=i;vis[i]=1;int hea=0,tail=1;while(hea<tail){hea++;int u=que[hea];int sat=step[hea];d[i][u]=sat;if(d[i][u]-1>kk) d[i][u]=d[0][0];for(int j=head[u];j!=-1;j=edge[j].next){int v=edge[j].to;if(vis[v]==0){step[++tail]=step[hea]+1;que[tail]=v;vis[v]=1;}}}} for(int i=2;i<=n;i++){if(d[1][i]<3000&&d[1][i]>=0){dp[i][1]=val[i];vis2[i][1][i]=1;q[i][1][1]=i;}}for(int k=2;k<=4;k++){for(int i=2;i<=n;i++){int tmp=0;for(int j=2;j<=n;j++){if(d[i][j]==d[0][0]||i==j||d[i][j]<0) continue;if(vis2[j][k-1][i]==1) continue;if(dp[j][k-1]!=dp[0][0]){if(dp[j][k-1]>dp[i][k]){dp[i][k]=dp[j][k-1];tmp=j;}}}for(int j=1;j<=n;j++){q[i][k][j]=q[tmp][k-1][j];vis2[i][k][q[i][k][j]]=1;if(q[i][k][j]==0){q[i][k][j]=i;vis2[i][k][i]=1;break;}}dp[i][k]+=val[i];}}for(int i=2;i<=n;i++){if(d[i][1]>0&&d[i][1]<3000){maxn=max(maxn,dp[i][4]);}}cout<<maxn;return 0;} 

假期计划(holiday)【CSPS2022】相关推荐

  1. [CSP-S 2022] 假期计划

    题目传送门 [CSP-S 2022] 假期计划(民间数据) 题目描述 小熊的地图上有 n n n 个点,其中编号为 1 1 1 的是它的家.编号为 2 , 3 , - , n 2, 3, \ldots ...

  2. 关于 [CSP-S 2022] 假期计划 的一些想法

    关于 [CSP-S 2022] 假期计划 的一些想法 洛谷链接 考场算法 这题暴力其实很好想,但是我觉得暴力太低级了,所以就直接跳过了第一步.然而我的分数其实比暴力的还少一点(悲). 首先,为了判断能 ...

  3. 【spfa】假期计划(jzoj 3936)

    假期计划 jzoj 3936 题目大意 给你一个有向图(n,m⩽20000n,m\leqslant 20000n,m⩽20000),现在有一些作为枢纽的点,且保证每一条边的两个点至少有一个是枢纽点,现 ...

  4. [CSP-S 2022] 假期计划题解

    假期计划 题目来源: CSP-S 2022 T1 题目描述 小熊计划从家出发去 4 4 4 个不同的景点游玩,完成 5 5 5 段行程后回家:家 → 景点 A A A → 景点 B B B → 景点 ...

  5. 【题解】P8817 [CSP-S 2022] 假期计划(bfs,dfs)

    [题解]P8817 [CSP-S 2022] 假期计划 此题作为 CSP-S 的 T1,可以说是相当有难度了.感觉 T1 和 T2 换了个位置.(雾) 我作为场外 VP 选手赛时此题只得了 95pts ...

  6. 计算机假期计划内容,2019寒假计划,超详细学习计划表

    [导语]愉快的寒假已经开始了,基于拓宽知识面的目的,按时学习生活,做事有规律,度过一个快乐充实有意义的寒假,因此制定一个合理的寒假学习计划对初中孩子们是非常有必要的.下面为您制定具体计划如下.以下内容 ...

  7. 计算机假期计划内容,寒假计划表内容

    寒假计划表内容 在经过紧张的期末考试之后,同学们即将迎来寒假生活,在迎接假期的同时同学们有没有制定好假期的计划呢? 寒假计划表内容 例1 对于初三的学生来说,利用寒假做好复习是非常重要的. 1.理规划 ...

  8. hihocoder #1698 假期计划 (排列组合+费马小定理+乘法逆元)

    Description 小Ho未来有一个为期N天的假期,他计划在假期中看A部电影,刷B道编程题.为了劳逸结合,他决定先拿出若干天看电影,再拿出若干天刷题,最后再留若干天看电影.(若干代指大于0)  每 ...

  9. [USACO09HOL]假期绘画Holiday Painting

    观察到列数只有15,可以想到对于每一列维护一颗线段树 sum表示该区间与目标矩阵中该区间相同元素个数 lazy表示该区间应被修改成什么颜色 g即目标矩阵中该区间白色格子的个数 显然一个区间的sum=区 ...

最新文章

  1. phpstorm安装_PHPstorm设置浏览器打开代码
  2. 不要相信修改注册表EnablePrefetcher文件达到加速开机速度的说法
  3. golang 中的 init 和 main函数
  4. MyBatis 的执行流程,写得太好了!
  5. OGG 跳过事务(转)
  6. 第四百一十七天 how can I 坚持
  7. 分布式应用架构中的数据传输对象(DTO)
  8. 高级筛选的以公式结果为条件
  9. python内置函数可以用来_Python内置函数——compile
  10. 101个免费的VMware工具
  11. Introduction to Computer Networking学习笔记(二十三):拥塞控制-TCP Tahoe
  12. 一款在线画图工具的使用(推荐)
  13. VFL-SFP业界首个光纤可视化故障定位器SFP模块
  14. poj3259 Wormholes floyd求负环
  15. unraid系统安装ikuai和openwrt虚拟机
  16. 我的世界mod服务器详细搭建
  17. 高中数学必修3知识点总结归纳:第三章概率
  18. 垃圾邮件的判定标准与识别方法
  19. 读松下幸之助自传有感
  20. 迈出高效管理步伐 8thManage助IT分销行以快制胜

热门文章

  1. 香港科大2020十大准独角兽 震撼发布!
  2. 湖南工业大学电费数据抓取(完美校园版)
  3. 自己写的流量波动检测函数 --37开发
  4. Dynamics 365(CRM) 欢迎加入商务技术交流QQ群(MSCRM商务技术交流群149371424)
  5. Windows 应急响应辅助笔记
  6. bat文件打开cmd指向某个目录,并执行命令
  7. android sdk版本
  8. cpprestsdk 上传和下载文件
  9. 视源股份笔试之挖个坑我就跳
  10. python使用pika操作rabbitmq总结(一)