【HDU - 4784】Dinner Coming Soon(记忆化搜索bfs,dp)

题干:

  Coach Pang loves his boyfriend Uncle Yang very much. Today is Uncle Yang’s birthday, Coach Pang wants to have a romantic candlelit dinner at Uncle Yang’s house and he has to arrive there in T minutes. 
  There are N houses in their city numbered from 1 to N. Coach Pang lives in house 1 while Uncle Yang lives in house N. The houses are connected byM directed roads. It takes some time and usually a fee to pass one road. Coach Pang wants to reach Uncle Yang’s house before the dinner starts with as much money as possible. 
  But the matter is not so simple. Coach Pang decides to do some salt trade on the way to Uncle Yang’s house. The host of each house offers a price of a bag of salt, so Coach Pang can make a profit from the price differences. Each time when Coach Pang arrives at a house (except the house 1 and the house N). He can buy one bag of salt, sell one bag of salt or do nothing. Coach Pang can carry at most B bags of salt with him, and he carries no salt when he leaves his house. The trading is so efficient that the time cost of trading can be ignored. 
  However, the problem is more complicated than imagine. Coach Pang has a handheld device that can perform a journey around K parallel universes numbered from 0 to K-1. Coach Pang lives in the universe 0. When Coach Pang uses the device in universe i, he will be transported to the same place and the same time of universe (i+1) modK. The host of the house at the same place in different universe may offer a different price of salt. Luckily, the time cost and fee of the city roads are uniform among the K universes. The journey between universes costs no time but Coach Pang has to stand still watching the ads on the device for one minute every time before the device works. Remember, Coach Pang should never visit house 1 or house N in a universe other than universe 0, because the situation might become uncontrollable if he bumps into himself or his boyfriend in another universe. 
  The time is running out. Coach Pang asks you to tell him whether he can arrive at Uncle Yang’s house in time, and how much money Coach Pang can have at most when the dinner starts. Coach Pang has R yuan at the start, and will end his journey immediately once he arrives at Uncle Yang’s house. He must arrive at Uncle Yang’s house in T minutes, and he can’t have negative amount of money anywhere anytime. Please help him!

Input

  The first line of the input is an integer C representing the number of test cases. 
  For each test case, the first line will contain 6 integers N, M, B, K, R, T, as described above. 
  (2 <= N <= 100, 0 <= M <= 200, 1 <= B <= 4, 2 <= K <= 5, 0 <= R <= 10 5, 0 <= T <= 200) 
  The following K lines contain N integers each, indicating the price p ij (0 <= i < K, 1 <= j <= N) for a bag of salt offered by the host of house j in the universe i. The price of house 1 and house N will be marked as -1.(1 <= p ij <= 100) 
  Then M lines follow, each contains 4 integers a, b, t and m, indicating that there is a road from house a to house b that costs t minutes of time and m yuan of money. (1 <= a,b <= N, a<> b, 1 <= t <=15, 0 <= m <= 100) 

Output

  For each test case, output one line containing “Case #x: y”, where x is the case number (starting from 1) and y is the most money Coach Pang can have if he can have dinner with Uncle Yang on time. 
  Print "Forever Alone" otherwise.

Sample Input

2
3 2 1 2 10 6
-1 1 -1
-1 5 -1
1 2 1 0
2 3 1 1
2 2 1 2 5 5
-1 -1
-1 -1
1 2 10 2
1 2 2 10

Sample Output

Case #1: 17
Case #2: Forever Alone

题目大意:

给定输入:N个点, M条单向边, 最多携带B袋食盐, K个平行宇宙, 最初有R元钱, 要求在T时间内到达。然后输入K行每行n个数代表当前宇宙当前城市的食盐价格。然后输入M行道路信息a, b, t ,m,代表a->b的单向边,耗费时间t,过路费m。

给定一张图,有N个城市M条单向道路,每条道路有须要消耗的时间t以及过路费m,一个人要在T分钟的时间内,从自己的城市(下标为1)赶到他男朋友的城市(下标为n),这个人最初有R元,为了在到男朋友家的同时赚更多的钱,在路途中还可以顺路做食盐生意,每个城市有一个食盐价格(不论是买还是卖都是这个价格)。起初身上没有食盐,某一个时刻身上最多带B袋盐。每到达一个有三种操作能够选择:1.售出一袋食盐、2.购买一袋食盐、3.什么都不做。(这三种操作的时间忽略不计)。同时,还存在K个平行宇宙,在一个城市能够选择穿越平行宇宙到达另一个宇宙的这个城市,花费时间为1,不同宇宙的同一城市食盐价格不同,可是不同宇宙同一道路的过路费和消耗的时间是相同的,题目还有一个限制条件:这个人不能在别的宇宙回到自己家或者男朋友家,求最后是否能到达他男朋友家以及最多能有多少钱。

解题报告:

不同于一般的记忆化bfs,这题的 时间 要素既是优先队列的key,又是dp中的一个维度。

这是因为你最终要求的是最大钱数,所以dp代表的含义就应该是钱数,而时间这个要素又不能忽略,所以就放到状态中去了。

dp[pos][t][b][k]代表当前在pos号点,t时刻,携带了b袋盐,在第k个平行宇宙时的最大钱数。算一下总状态数100*200*4*5很小,所以可以直接bfs。

注意代码中那个入队的限制:仅在第一次更新的时候入队,是为了优化时间,不加那个if判断而是直接push进去的话也可以过。

一般的bfs中都是加一个bool类型的vis数组,当数组值为0的时候才push,这里的dp值=-1的时候才push是一个道理。但是这里是否可以这样呢?一般的时候都是一个状态然后代表到达这个状态的最短时间,所以随着时间的推移这个状态肯定不会被遍历到了,或者遍历到的时候可以直接continue,因为要求的是最短时间,所以可以直接状态只入队一次,因为只可能更新一次。

但是这个题,明明可能更新这个状态很多次,为什么还是可以直接=-1的时候就入队,再往后的更新都不需要入队了呢?因为我们把时间的维度加到状态里面去了,而pq里面又是按照时间作为关键字,所以当我取到这个状态x的时候,就意味着后面所有出现的状态都不可能再去更新状态x了,因为时间肯定是变了的,所以当前dp值就不可能再改变了,也就是说这就是个完成值了,所以只需要进队一次,作用是:来代表可以取出来用这个状态继续更新其他值。就可以了。所以队列中只需要记录这个状态一次。

再一个不同就是pq维护的Node节点信息不同,一般的是dp值在里面:比如搜索地图的时候,时间信息在里面;比如Dijkstra中,最短距离在里面。而这个题,dp值是最大金钱,而这个信息并没有在里面。

究其原因就是发现,一般的时候其实dp的值也可以不放进去,但是因为我们经常需要这个dp值去当关键字key扔到pq中,所以把dp值信息加到了key中。所以更一般来讲,Node中维护的信息一般就是dp数组的维度的元素含义就可以了,而值的含义理论上不需要放进去。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
int N,M,B,K,R,T; 
int p[12][111];//p[i][j]第i+1个平行宇宙的第j号顶点的价格 p[5][101]
int dp[111][222][5][11];//dp[pos][t][b][k]
struct Edge {int fr,to;int cost,t;int ne;
} e[205];
int tot;
int head[MAX]; 
void add(int u,int v,int t,int cost) {e[++tot].fr = u;e[tot].to = v;e[tot].cost = cost;e[tot].t = t;e[tot].ne = head[u];head[u] = tot;
}
struct Node {int pos,t,b,k;Node(){}Node(int pos,int t,int b,int k):pos(pos),t(t),b(b),k(k){}operator < (const Node & b) const {return t > b.t;} 
};
void bfs() {priority_queue<Node>pq;pq.push(Node(1,0,0,0));dp[1][0][0][0]=R;while(pq.size()) {Node cur = pq.top();pq.pop();if(cur.pos == N) continue;int curmoney = dp[cur.pos][cur.t][cur.b][cur.k];for(int i = head[cur.pos]; ~i; i = e[i].ne) {int nowmoney = curmoney - e[i].cost;if(nowmoney < 0) continue;//如果金钱不够则GGif(cur.t + e[i].t > T) continue;//如果已经超时了则GG if((e[i].to == 1 || e[i].to == N) && cur.k!=0) continue;//如果不在1号宇宙则GG。注意不能写(k!=0&&k!=K-1),因为你这层for处理的都是在同一层宇宙的操作 //现在说明我可以走到下一个点了if(nowmoney > dp[e[i].to][cur.t + e[i].t][cur.b][cur.k]) {if(dp[e[i].to][cur.t + e[i].t][cur.b][cur.k] == -1) pq.push(Node(e[i].to,cur.t + e[i].t,cur.b,cur.k));dp[e[i].to][cur.t + e[i].t][cur.b][cur.k] = nowmoney;} //下面是在e[i].to这里同时进行买卖一波的话if(p[cur.k][e[i].to] == -1) continue; //如果还能买 if(cur.b < B && nowmoney - p[cur.k][e[i].to] >= 0) {if(nowmoney - p[cur.k][e[i].to] > dp[e[i].to][cur.t + e[i].t][cur.b+1][cur.k]) {if(dp[e[i].to][cur.t + e[i].t][cur.b+1][cur.k] == -1) pq.push(Node(e[i].to,cur.t + e[i].t,cur.b+1,cur.k));dp[e[i].to][cur.t + e[i].t][cur.b+1][cur.k] = nowmoney - p[cur.k][e[i].to] ;}}if(cur.b > 0) {//不用加上面那个判断因为这里肯定是大于零的 if(nowmoney + p[cur.k][e[i].to] > dp[e[i].to][cur.t + e[i].t][cur.b-1][cur.k]) {if(dp[e[i].to][cur.t + e[i].t][cur.b-1][cur.k] == -1) pq.push(Node(e[i].to,cur.t + e[i].t,cur.b-1,cur.k));dp[e[i].to][cur.t + e[i].t][cur.b-1][cur.k] = nowmoney + p[cur.k][e[i].to] ;}}}if(cur.pos == 1 || cur.pos == N) continue;if(cur.t + 1 > T) continue; int nowk = (cur.k + 1) % K;if(curmoney > dp[cur.pos][cur.t+1][cur.b][nowk]) {if(dp[cur.pos][cur.t+1][cur.b][nowk] == -1) pq.push(Node(cur.pos,cur.t+1,cur.b,nowk));dp[cur.pos][cur.t+1][cur.b][nowk] = curmoney;}if(cur.b < B && curmoney - p[nowk][cur.pos] >= 0) {if(curmoney - p[nowk][cur.pos] > dp[cur.pos][cur.t + 1][cur.b+1][nowk]) {if(dp[cur.pos][cur.t + 1][cur.b+1][nowk] == -1) pq.push(Node(cur.pos,cur.t + 1,cur.b+1,nowk));dp[cur.pos][cur.t + 1][cur.b+1][nowk] = curmoney - p[nowk][cur.pos] ;}}if(cur.b > 0) {if(curmoney + p[nowk][cur.pos] > dp[cur.pos][cur.t + 1][cur.b-1][nowk]) {if(dp[cur.pos][cur.t + 1][cur.b-1][nowk] == -1)pq.push(Node(cur.pos,cur.t + 1,cur.b-1,nowk));dp[cur.pos][cur.t + 1][cur.b-1][nowk] = curmoney + p[nowk][cur.pos] ;}}}
}
int main()
{int t,iCase=0;cin>>t;while(t--) {scanf("%d%d%d%d%d%d",&N, &M, &B, &K, &R, &T);//inittot=0;for(int i = 1; i<=N; i++) head[i] = -1;memset(dp,-1,sizeof dp);for(int k = 0; k<K; k++) {for(int i = 1; i<=N; i++) {scanf("%d",&p[k][i]);}}for(int a,b,t,m,i = 1; i<=M; i++) {scanf("%d%d%d%d",&a,&b,&t,&m);add(a,b,t,m);}bfs();int ans = -1;for(int i = 1; i<=T; i++) {if(dp[N][i][0][0] > ans) ans = dp[N][i][0][0];}printf("Case #%d: ",++iCase);if(ans == -1) printf("Forever Alone\n");else printf("%d\n",ans);}return 0 ;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/440203.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux操作系统CentOS7安装

最近在学习Linux&#xff0c;今天记录下如何安装CentOS7操作系统。 1. 下载虚拟机软件 虚拟机选择的是VMware Workstation软件&#xff0c;可以访问这个链接下载&#xff1a;https://coding.net/u/aminglinux/p/resource/git/blob/master/README.md 2. 安装虚拟机 按照提示&…

div内容居中和布局居中样式总结

1.div的内容居中 &#xff08;1&#xff09;水平居中 <div align"center"><button>按钮></button></div> CSS&#xff1a; div{display: block; // div默认为块级元素&#xff0c;如果是第三方控件或继承父类元素不是block&#xff…

【HDU - 6349】三原色图(最小生成树,思维,tricks)

题干&#xff1a; 度度熊有一张 nn 个点 mm 条边的无向图&#xff0c;所有点按照 1,2,⋯,n1,2,⋯,n 标号&#xff0c;每条边有一个正整数权值以及一种色光三原色红、绿、蓝之一的颜色。 现在度度熊想选出恰好 kk 条边&#xff0c;满足只用这 k 条边之中的红色边和绿色边就能使…

机器学习初学者公众号下载资源汇总(一)

感谢黄海广博士的分享 原创&#xff1a; 机器学习初学者 机器学习初学者 今天 本站提供了大量的机器学习初学者下载资源&#xff0c;现在对已经公布的资源做下汇总&#xff0c;每个资源都会有一个百度云链接&#xff0c;并同时提供“自动回复”的功能&#xff08;有时候百度云链…

Oracle和MySQL多表条件分页查询的高效SQL语句、MySQL分页查询总数total的获取

Oracle数据库分页查询&#xff1a; 利用rownum和between and关键字 -- 查询员工表和薪水表的分页sql&#xff08;pageNo&#xff1a;页号从1开始&#xff0c;pageSize&#xff1a;每页大小&#xff09; select* from(selectROWNUM rNo,user_id,user_name,user_dept,user_sal…

[通俗易懂]深入理解TCP协议(下):RTT、滑动窗口、拥塞处理

转自即时通讯网&#xff1a;http://www.52im.net/ 前言 此文为系列文章的下篇&#xff0c;如果你对TCP不熟悉的话&#xff0c;请先看看上篇《[通俗易懂]深入理解TCP协议&#xff08;上&#xff09;&#xff1a;理论基础》 。 上篇中&#xff0c;我们介绍了TCP的协议头、状态机…

【HDU - 4781】Assignment For Princess(图上构造)

题干&#xff1a; Long long ago, in the Kingdom Far Far Away, there lived many little animals. And you are the beloved princess who is marrying the prince of a rich neighboring kingdom. The prince, who turns out to be a handsome guy, offered you a golden en…

Vim编辑器最常用的快捷键

Vim编辑器常用快捷键 光标移动到行首、行尾&#xff1a; 数字0/$ 光标移动到第一行、最后一行&#xff1a; 大写H/L 快速移动到第一行也可以用gg 光标移动到第几行、从当前位置跳跃几行&#xff1a; 行号大写G 跳…

脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手

转自即时通讯网&#xff1a;http://www.52im.net/ 1、引言 网络编程中TCP协议的三次握手和四次挥手的问题&#xff0c;在面试中是最为常见的知识点之一。很多读者都知道“三次”和“四次”&#xff0c;但是如果问深入一点&#xff0c;他们往往都无法作出准确回答。 本篇文章尝…

【HDU - 5452】Minimum Cut(树形dp 或 最近公共祖先lca+树上差分,转化tricks,思维)

题干&#xff1a; Given a simple unweighted graph GG (an undirected graph containing no loops nor multiple edges) with nn nodes and mm edges. Let TT be a spanning tree of GG. We say that a cut in GG respects TT if it cuts just one edges of TT. Since love…

Idea自带的工具打jar包和Maven打Jar包(SpringBoot工程)

1.Idea自带的工具打jar包 &#xff08;1&#xff09;点击菜单栏的File后选中Project Structure&#xff0c;接着按如下图所示操作&#xff1a; &#xff08;2&#xff09;点击“OK”按钮后会出现下图的界面&#xff0c;然后继续点击“OK”按钮 &#xff08;3&#xff09;现在开…

图解算法学习笔记(目录)

今天遇到一本好书&#xff0c;如下&#xff0c;书很薄&#xff0c;不到200页&#xff0c;有将近400张图片&#xff0c;算法介绍的很有趣。这也是我读的第三本袁国忠先生翻译的书&#xff0c;向两位致敬。 目录大致如下; 第1章&#xff1a;二分查找和大O表示法&#xff1b; 第…

2019ACM浪潮杯山东省赛参赛总结

emmm是要记录一下生活了呢&#xff0c;不然以后退役了连自己经历过什么都记不住了。 5.11周六&#xff0c;早上5:30分&#xff0c;qdu集训队一行40人(左右)集合登上大巴&#xff0c;前往济南大学参加ACM省赛。上车清点了一下人数&#xff0c;然后发车以后就睡着了&#xff0c;…

Linux系统查看开放的端口、开启指定端口、关闭指定端口和查看及删除定时任务

Linux系统管理端口的操作命令 以下操作在需要开启防火墙&#xff0c;防火墙的开启(重启)、关闭和查看防火墙的状态见末尾 1.查看所有已经对外开放的端口&#xff1a;firewall-cmd --list-ports 2.开启指定的端口&#xff1a;firewall-cmd --zonepublic --add-port8080/tcp -…

图解算法学习笔记(一): 算法简介

本章内容&#xff1a; 编写第一种查找算法——二分查找。 学习如何谈论算法的运行时间——大O表示法。 1) 算法是一组完成任务的指令&#xff0c;任何代码片段都可视为算法。 2)二分查找&#xff1a;一种查找算法&#xff0c;其输入是一个有序的元素列表。 Python实现二分查…

用友通ERP客户端报无法登陆错

用友通ERP客户端报“无法登陆”错 排除系统版本错&#xff0c;要求windows xp professional sp2&#xff1b;client.dll文件错误后 请确认 c:/windows/system32/drivers/etc/目录下存在 hosts 文件&#xff0c;并且含有 127.0.0.1 localhost 行

【POJ - 3249】Test for Job(DAG线性求带负权的最长路,dp)

题干&#xff1a; Mr.Dog was fired by his company. In order to support his family, he must find a new job as soon as possible. Nowadays, Its hard to have a job, since there are swelling numbers of the unemployed. So some companies often use hard tests for …

图解算法学习笔记(二): 选择排序

目录 1)数组和链表&#xff1a; 2)选择排序算法&#xff1a; 3)小结 本章内容&#xff1a; 两种基本数据结构&#xff1a;数组和链表&#xff1b; 选择排序算法&#xff1b; 1)数组和链表&#xff1a; 数组是连续的内存单元&#xff0c;链表可以不连续&#xff1b; 链表…

javascript递归遍历文件夹下面的所有文件并返回所有文件全路径名称数组以及解析JavaScript方法体字符串的结束位置

一、前端脚本经常需要用到遍历指定文件夹下面的所有文件&#xff08;包含子文件夹&#xff09;的内容并做特定的逻辑处理&#xff0c;下面给出同步遍历的方式&#xff0c;开箱即用。 const fs require(fs);main()function main() {let allFiles getAllFiles(srcDir);console…

WinXP下替代IIS的新思路

WinXP下&#xff0c;.Net服务器有两个选择&#xff0c;IIS和Webdev.webservice。然而&#xff0c;IIS有最多十连接的限制&#xff0c;网上的解决方式&#xff08;包括注册表修改、微软工具、NTSwitch&#xff09;均未能突破&#xff1b;webdev.webservice虽没有连接数量限制&am…