H

描述

xxxxxxxxx在疫情期间迷上了一款游戏,这个游戏一共有nnn个地点(编号为1——n1——n1——n),他每次从一个地点移动到另外一个地点需要消耗

一定的能量,每一个地点都有一些珠宝,输入中会把每一个地方的珠宝价值估算成一个值。

xxxxxxxxx想请聪明的你帮他找出来从编号为sss的地点,到编号为ddd的地点最小要消耗多少能量,消耗这些能量最多获得多少价值的珠宝

输入

第一行输入n,s,dn,s,dn,s,d。其意义如上描述 (n&lt;520n&lt;520n<520)

第二行有nnn个数XiX_iXi​,比如i==1i==1i==1描述编号为1的点有珠宝价值为XiX_iXi​(这里保证XiX_iXi​大于等于0) (Xi&lt;1000X_i&lt;1000Xi​<1000)

下面输入一个n∗nn*nn∗n的矩阵,比如第iii行,第j列的值为xxx,就表示从编号为iii到编号为jjj的地方距离为x (x&lt;1000)x  (x&lt;1000)x (x<1000)

注意:这是一个单向路,即从编号为iii到编号为jjj的距离可能不等于从编号为jjj到编号为iii

输出

输出占一行,第一个数是最小要消耗多少能量,第二个数是消耗这些能量最多获得多少价值的珠宝。两个数用空格分开

输入样例 1

4 1 4

20 30 40 10

0 1 2 3

999 0 999 2

999 999 0 2

999 999 999 0

输出样例 1

3 60

输入样例 2

7 2 3

341 527 189 740 490 388 989

0 489 711 174 305 844 971

492 0 998 954 832 442 424

619 906 0 154 293 395 439

735 738 915 0 453 748 786

550 871 932 693 0 326 53

904 732 835 354 364 0 691

669 157 719 282 875 573 0

输出样例 2

998 716

提示

第一个样例解释:

解释:

把这个矩阵翻译成边

1->2 1

2->4 2

1->4 3

1->3 2

3->4 2

正确路径:1->2->4

 

 

题目正解:最短路+dfs 或 最短路+dp。

题目灵感:L2-001 紧急救援 (25分)。

题目大意描述:

让你找出来最短路径,如果最短路径有多条,那就取出来每一条路径中 所有点权值之和 最大的那个路径(点权值是什么意思?就是题目中说的每一个点的珠宝价值)

题目解法1:最短路+dfs

按照题目描述我们就需要先找出来最短路的大小,然后我们知道这个大小之后就dfs去跑图,找到每一条能从起点s到终点d的路径,然后每一条路径肯定有一个路径长度,我们只保留那个与最短路大小相等的长度的路径

然后对每一条路径在dfs过程中记录它所经过每一个点,把这些点的权值加到一起,我们设这个值为总值

那么每一条路径都有一个总值,我们只需要从中找出来最大的那个输出就行

Dfs代码如下:

void dfs(int x,int value)
{
if(x==d)
{
if(result<value)
{
result=value;
}
return;
}
for(int i=1; i<=n; ++i)
{
if(!vis[i] && dist[i]==dist[x]+G[x][i] && G[x][i])
{
vis[i]=1;
dfs(i,value+val[i]);
vis[i]=0;
}
}
}

这里我们为了避免盲目的搜索所有路径,我们可以加一个限制条件来优化dfs:

dist[i]==dist[x]+G[x][i]   //dist是我们跑最短路之后跑出来的单源最短路数组

假设一条路径例如s->2->3->d,如果你dfs过程中s->2->3的长度不等于dist[3] ,那么就算dfs到终点d这条路径长度绝对不可能等于dist[d]

至于为什么这里就不多说了,自己想一下

代码:

  1 #include<stdio.h>
2 #include<string.h>
3 #include<iostream>
4 #include<algorithm>
5 #include<queue>
6 #include<vector>
7 using namespace std;
8 typedef long long ll;
9 const int inf = 0x3f3f3f3f;
10 const int maxn = 550;
11 int n,m,s,d;
12 int val[maxn],vis[maxn],dist[maxn];
13 int G[maxn][maxn],result;
14 int int_rand(int min,int max)
15 {
16 return int(min+rand()%(max-min));
17 }
18 struct shudui1
19 {
20 int start,value;
21 bool operator < (const shudui1 q)const
22 {
23 return value<q.value;
24 }
25 } str1;
26 priority_queue<shudui1>r;
27 void dijkstra()
28 {
29 memset(vis,0,sizeof(vis));
30 memset(dist,inf,sizeof(dist));
31 dist[s]=0;
32 str1.start=s;
33 str1.value=0;
34 r.push(str1);
35 while(!r.empty())
36 {
37 int x,y;
38 str1=r.top();
39 r.pop();
40 x=str1.start;
41 y=str1.value;
42 if(dist[x]<y) continue;
43 for(int i=1; i<=n; ++i)
44 {
45 if((dist[x]+G[x][i]<dist[i]))
46 {
47 dist[i]=dist[x]+G[x][i];
48 str1.start=i;
49 str1.value=dist[i];
50 r.push(str1);
51 }
52 }
53 }
54 }
55 void dfs(int x,int value)
56 {
57 if(x==d)
58 {
59
60 if(result<value)
61 {
62 result=value;
63 }
64 return;
65 }
66 for(int i=1; i<=n; ++i)
67 {
68 if(!vis[i] && dist[i]==dist[x]+G[x][i] && G[x][i])
69 {
70 vis[i]=1;
71
72 dfs(i,value+val[i]);
73
74 vis[i]=0;
75 }
76 }
77 }
78 int main()
79 {
80 int u,v,w;
81 scanf("%d%d%d", &n, &s, &d);
82 for(int i = 1; i <= n; i ++)
83 {
84 scanf("%d", &val[i]);
85 }
86 for(int i = 1; i <= n; i ++)
87 {
88 for(int j = 1; j <= n; j ++)
89 {
90 scanf("%d",&G[i][j]);
91 }
92 }
93 dijkstra();
94 result=0;
95 memset(vis,0,sizeof(vis));
96 vis[s]=1;
97 dfs(s,val[s]);
98 printf("%d %d\n",dist[d],result);
99 return 0;
100 }

题目解法2:最短路+dp

题外话:这个方法其实我并没有想到,还是yzj验题之后给me说的(牛掰)

for(ll i=0; i<len; i++)
{
ll v=vec[t][i].v;
ll w=vec[t][i].w;
if(dis[t]+w<dis[v])
{
dp[v]=dp[t]+sc[v]; //当s->v的最短路径已然变得更小,那么dp值要重新赋值,而不是比较之后再赋值
dis[v]=dis[t]+w;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
else if(dis[t]+w==dis[v]) //相对于原版spay算法,这里多了一个判断。多这个判断的意义和上面第一种解法的dfs里面多一个判断那个差不多
{
if(dp[v]<dp[t]+sc[v])//这里要想给dp[v]赋值就要通过判断,因为我们要输出总值最大的那个路径
{
dp[v]=dp[t]+sc[v];
if(!vis[v])
{
vis[v]=1;
q.push(v);//如果这个点满足条件,那么我们还要把这个点放入队列,那么相比于原spay算法这个代码复杂度就要大一点,但是还是要比第一种方法复杂度低
}
}
}
}

Dp关键部分就是上面代码,也就是在spay算法的while循环里面

解释一下每一个数组:

Dis数组是存放单源最短路结果

Vis数组是用来标记某一个点是否进入队列中(等于1就代表在队列)

Dp[i]数组初值是等于i点的权值(点权值是什么意思?就是题目中说的每一个点的珠宝价值),这个数组的作用就是找出来题目第二个输出结果

Sc[]数组初值是等于i点的权值

代码:

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define ll long long
4 const ll maxn=2e3+5;
5 ll sc[maxn],dis[maxn],vis[maxn],ans;
6 ll dp[maxn],pre[maxn];
7 struct node
8 {
9 ll v,w;
10 } p;
11 vector<node>vec[maxn];
12 vector<ll>ve[maxn];
13 queue<ll>q;
14 void spfa(ll u)
15 {
16 memset(dis,0x3f3f3f3f,sizeof(dis));
17 memset(vis,0,sizeof(vis));
18 dis[u]=0;
19 q.push(u);
20 while(!q.empty())
21 {
22 ll t=q.front();
23 vis[t]=0;
24 q.pop();
25 ll len=vec[t].size();
26 for(ll i=0; i<len; i++)
27 {
28 ll v=vec[t][i].v;
29 ll w=vec[t][i].w;
30 if(dis[t]+w<dis[v])
31 {
32 dp[v]=dp[t]+sc[v];
33 dis[v]=dis[t]+w;
34 if(!vis[v])
35 {
36 vis[v]=1;
37 q.push(v);
38 }
39 }
40 else if(dis[t]+w==dis[v])
41 {
42 if(dp[v]<dp[t]+sc[v])
43 {
44 dp[v]=dp[t]+sc[v];
45 if(!vis[v])
46 {
47 vis[v]=1;
48 q.push(v);
49 }
50 }
51 }
52 }
53 }
54 }
55 int main()
56 {
57 ios::sync_with_stdio(false);
58 cin.tie(0);
59 ll n,s,d;
60 cin>>n>>s>>d;
61 for(ll i=1; i<=n; i++)
62 cin>>sc[i],dp[i]=sc[i];
63 ll w;
64 for(ll i=1; i<=n; i++)
65 for(ll j=1; j<=n; j++)
66 {
67 if(i==j)
68 cin>>w;
69 else
70 cin>>w,p.v=j,p.w=w,vec[i].push_back(p);
71 }
72 spfa(s);
73 cout<<dis[d]<<' '<<dp[d]<<endl;
74 }

nuoyanli 520 Let‘s play computer game的更多相关文章

  1. L3-007 天梯地图 (30分) 最短路+dp

    最短路+dp思路:nuoyanli 520 Let's play computer game 输入样例1: 10 15 0 1 0 1 1 8 0 0 1 1 4 8 1 1 1 5 4 0 2 3 ...

  2. Stack switching mechanism in a computer system

    A method and mechanism for performing an unconditional stack switch in a processor. A processor incl ...

  3. Let‘s play computer game(最短路 + dfs找出所有确定长度的最短路)

    Let's play computer game Description xxxxxxxxx在疫情期间迷上了一款游戏,这个游戏一共有nnn个地点(编号为1--n1--n1--n),他每次从一个地点移动 ...

  4. 共享文件夹:The user has not been granted the requested logon type at this computer

    场景重现 今天做一个项目测试,要用到虚拟机,于是在虚拟机(XP 32)上新建了一个共享的文件夹.然后我在Win7 机器上访问它得到如下的error 消息:

  5. 1Z0-053 争议题目解析520

    1Z0-053 争议题目解析520 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 520.Which of the following are not disabled by de ...

  6. Computer assisted surgery

    Computer assisted surgery (CAS) represents a surgical concept and set of methods, that use computer ...

  7. Computer vision labs

    积累记录一些视觉实验室,方便查找 1.  多伦多大学计算机科学系 2.  普林斯顿大学计算机视觉和机器人实验室 3.  牛津大学Torr Vision Group 4.  伯克利视觉和学习中心 Pro ...

  8. Computer Vision: OpenCV, Feature Tracking, and Beyond--From <<Make Things See>> by Greg

    In the 1960s, the legendary Stanford artificial intelligence pioneer, John McCarthy, famously gave a ...

  9. 数论 - Vanya and Computer Game

    Vanya and his friend Vova play a computer game where they need to destroy n monsters to pass a level ...

随机推荐

  1. Redis 5 配置 Redis sentinel(哨兵模式)

    先了解一下哨兵都 做了什么工作:Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务: * 监控(Monitoring): Sentin ...

  2. SQL查找连续出现的数字

    基于Oracle: 题:编写一个 SQL 查询,查找所有至少连续出现三次的数字. +----+-----+ | Id | Num | +----+-----+ | 1 | 1 | | 2 | 1 | ...

  3. 映泰主板H100系列安装win7的各种坑

    自100系列主板发布以来,windows7好像就被遗弃一样,原因就在于安装win7的时候,会出现USB设备无法使用导致无法安装的问题.主要在于Win7系统没有整合USB的XHCI驱动,而100系列芯片 ...

  4. kubernets之DaemonSet

    一  k8s资源之DaemonSet 1.1 介绍认识DaemonSet DaemonSet可以理解为一种比较特殊的RS,DaemonSet的作用是永远保持被指定的节点只运行一个pod的副本,可用作集 ...

  5. Log4j日志记录

    1.导入log4j的jar包 2.写log4j.properties文件,配置日志记录参数,一般参数如下所示: 第二行指定了输出日志的目录,此处用的相对路径,也可换成绝对路径: 第三行指定了输出的记录 ...

  6. LeetCode590. N叉树的后序遍历

    题目 1 class Solution { 2 public: 3 vector<int>ans; 4 vector<int> postorder(Node* root) { ...

  7. CVE-2020-0796复现

    今天整理资料时发现了之前存的一个cve漏洞复现过程,当时打算跟着复现来着,后来也没去复现,今天刚好有时间,所以来复现一下这个漏洞 漏洞讲解 https://www.freebuf.com/vuls/2 ...

  8. SAP FTP FOR ABAP programing

    近来忙的不可开交,忙的一塌糊涂,呵呵,今天怀揣愧疚之心,上来分享博文一篇,算是对自己的一点安慰.   首先在SAP系统中提供了很多的FTP示例程序,如下: RSFTP001         SAPFT ...

  9. CodeMonkey少儿编程第2章 turnTo对象

    目标 了解对象的概念 了解方法与对象的关系 掌握turnTo指令的用法 在开始本章的学习之前,我们先来复习一下上一章的知识点. 在第1章中,我们学会了在这个游戏中最简单的两个指令. step x 其中 ...

  10. openshift 3.11安装部署

    openshift 3.11 安装部署 openshift安装部署 1 环境准备(所有节点) openshift 版本 v3.11 1.1 机器环境 ip cpu mem hostname OSsys ...