题干:

  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 ;
}

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

  1. 记忆化搜索(DFS+DP) URAL 1223 Chernobyl’ Eagle on a Roof

    题目传送门 1 /* 2 记忆化搜索(DFS+DP):dp[x][y] 表示x个蛋,在y楼扔后所需要的实验次数 3 ans = min (ans, max (dp[x][y-i], dp[x-1][i ...

  2. HDU 1176 免费馅饼(记忆化搜索)

    免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  3. HDU 2452 Navy maneuvers (记忆化搜索)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2452 题意:给出一个图,n个点,m条边,保证无环,每个点有一个权值.指定一个点作为起点,Victory和G ...

  4. 【HDU - 2571】 命运(记忆化搜索)

    题干: 穿过幽谷意味着离大魔王lemon已经无限接近了!  可谁能想到,yifenfei在斩杀了一些虾兵蟹将后,却再次面临命运大迷宫的考验,这是魔王lemon设下的又一个机关.要知道,不论何人,若在迷 ...

  5. BZOJ1415[Noi2005]聪聪和可可——记忆化搜索+期望dp

    题目描述 输入 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行 ...

  6. 搜索问题之状态空间搜索(状态压缩+记忆化搜索+ BFS)

    文章目录 1. 前言 2. 问题举例(九宫格问题) 3. 问题分析 3.1 状态编码与解码 3.2 哈希映射 3.3 集合判重 4. 问题实现 推荐阅读 1. 前言 之前介绍的回溯法常用于 解空间的搜 ...

  7. 【HDU 1501】Zipper(记忆化搜索)

    传送门 我们记录pos1 pos2 pos3 分别代表现在字符串1,2,3的位置 然后判断pos1是否等于pos3 或者pos2是否等于pos3 分别进行dfs 然后我们发现是可以记忆化的 比方当po ...

  8. 【POJ - 1661】Help Jimmy(记忆化搜索,dp)

    题干: Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无限. Jimmy老鼠在时刻0从高于所有平台的某处开 ...

  9. jzoj6451-[2020.01.19NOIP提高组]不幸运数字【记忆化搜索,数位dp,高精度】

    正题 题目链接:https://jzoj.net/senior/#main/show/6451 题目大意 给出a,ba,ba,b,求[a,b][a,b][a,b]这个区间中有多少数字包含444. 解题 ...

最新文章

  1. 假笨说-从一起GC血案谈到反射原理
  2. [翻译]RobotTurK: 灾难情况紧急视频系统
  3. 浅谈javascript继承【读javascript设计模式第四章节继承有感】
  4. selenium 鼠标悬浮_处理Selenium3+python3定位鼠标悬停才显示的元素
  5. python接口自动化(四)--接口测试工具介绍(详解)
  6. 卓越领导者的智慧(精华版)
  7. 封装scrollView 循环滚动,tableViewCell(连载) mvc
  8. Github新功能 个人展示项目--首页展示个人介绍 图片and so on(2020.08.05)
  9. OrCAD Capture CIS 16.6 修改原理图的页面大小
  10. qmessagebox 设置显示屏幕中间_windows7屏幕分辨率设置
  11. javascript中concat方法深入理解
  12. symantec BESR 异机恢复
  13. loadrunner11 java脚本_LoadRunner11开发Java Vuser协议脚本
  14. ExtJS2.0 可编辑表格EditorGridPanel
  15. 亚马逊平板刷机Linux系统,亚马逊平板刷机步骤盘点【图解】
  16. 远程桌面连接:使用lcx进行端口转发
  17. 服务器端与客户端之间进行数据传输与交换的格式(xml与JSON)
  18. EXTJS入门教程及其框架搭建
  19. 004 无损分区4k对齐
  20. Xilinx 7系列FPGA中CLB结构和内部资源使用

热门文章

  1. 关于客户端无法获得服务器端GP服务(Geoprocessing Service)结果的解决办法
  2. 动态规划——硬币找零思路
  3. pta - 1132 Cut Integer
  4. php.ini 老薛,出现Allowed memory size of 134217728 bytes exhausted怎么办?
  5. java web.xml 监听器_【JAVA 核心技术】java web 中的监听器
  6. python爬取知乎问题_python爬取知乎首页问题
  7. jquery查找ul属性不是hide,jQuery的ul显示/隐藏功能
  8. webgl 游戏_如何选择 WebGL 框架和引擎?
  9. springboot整合elasticsearch_Spring Boot学习10_整合Elasticsearch
  10. activex控件 新对象 ocx 初始化_Office已经支持64位的树控件Treeview了