日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/10 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【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 ; }

?

總結

以上是生活随笔為你收集整理的【HDU - 4784】Dinner Coming Soon(记忆化搜索bfs,dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。