UESTC_酱神寻宝 2015 UESTC Training for Dynamic ProgrammingProblem O
O - 醬神尋寶
Time Limit: 3000/1000MS (Java/Others) ??? Memory Limit: 65535/65535KB (Java/Others)
Submit?Status醬神來到了一座小島,島上有n個箱子。
一共有3中不同的鑰匙,金鑰匙、銀鑰匙和萬能鑰匙。醬神一開始有a把金鑰匙、b把銀鑰匙和c把萬能鑰匙。
第i個箱子上有xi把金鎖,yi把銀鎖。金鑰匙只能打開金鎖,銀鑰匙只能打開銀鎖,萬能鑰匙兩種鎖都能打開。用于打開鎖的鑰匙會立刻損壞,醬神會丟掉損壞的鑰匙。箱子里有ai把金鑰匙、bi把銀鑰匙和ci把萬能鑰匙,想要取出箱內的鑰匙必須要打開這xi+yi把鎖。
醬神的目的是使他擁有的鑰匙總數最多。一旦醬神認為自己已經擁有了最多的鑰匙,他就不會去開剩下的箱子了。
Input
第一行一個數n。
接下來有n行。每行5個數,xi,yi,ai,bi,ci。
最后一行3個數a,b,c。
1=<n<=15
0=<xi,yi,ai,bi,ci,a,b,c<=10
Output
輸出一個數醬神的最多鑰匙數。
Sample input and output
| 3 1 0 0 0 1 2 4 0 8 0 3 9 10 9 8 3 1 2 | 8 |
| 1 0 0 1 2 3 0 0 0 | 6 |
Hint
第一個樣例中醬神會打開第一個和第二個箱子。
?
解題思路:
首先貪心,能用金 / 銀就不用萬能鑰匙.
我們不妨令 f ( i , j ) -> 開啟箱子的狀態為 i , 金鑰匙為 j 把時能獲得最多的萬能鑰匙.
之后我們考慮更新,設 0 為沒開啟過, 1 為開啟過.
每次更新都是由 x 個 0 的狀態更新到 x+1 個 0 的狀態.
我們采用bfs維護這種順序即可
?
不過由于本題數據很水,各位可以嘗試各種花式方法水過去!!
?
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <queue> /*f( i , j ) - > 當前開的箱子的集合為 i , 金鑰匙的數目是 j 時可以獲得的最多萬能鑰匙數目. */using namespace std; const int maxn = 15; int n,sta,stb,stc,f[1 << 15][ maxn*11 ],ans = 0; typedef struct Item {int needA,needB,getA,getB,getC; };typedef struct updatastatus {int st,number; updatastatus(const int &st,const int &number){this->st = st , this->number = number;} };bool arrived[1 << 15][maxn * 11]; queue<updatastatus>q; Item A[maxn+3];inline void updata(int i,int j,int newans) {f[i][j] = max(f[i][j],newans); }//可以開啟為 0 , 不能開啟為 1; int main(int argc,char *argv[]) {scanf("%d",&n);for(int i = 0 ; i < n ; ++ i) scanf("%d%d%d%d%d",&A[i].needA,&A[i].needB,&A[i].getA,&A[i].getB,&A[i].getC);scanf("%d%d%d",&sta,&stb,&stc);f[0][sta] = stc; // Init;memset(arrived,false,sizeof(arrived));q.push(updatastatus(0,sta));while(!q.empty()){updatastatus ns = q.front();q.pop();int ra = ns.number, rb, rc = f[ns.st][ns.number] , all = sta + stb + stc , st = ns.st;for(int i = 0 ; i < n ; ++ i)if (ns.st >> i & 1)all += A[i].getA + A[i].getB + A[i].getC - A[i].needA - A[i].needB;ans = max(ans,all);rb = all - ra - rc;for(int i = 0 ; i < n ; ++ i){if (!(st >> i & 1)){int needA = A[i].needA;int needB = A[i].needB;int getA = A[i].getA;int getB = A[i].getB;int getC = A[i].getC;if (ra >= needA) //金夠 {if (rb >= needB) //金銀都夠 {updata(st | (1 << i) , ra - needA + getA, rc + getC);if (!arrived[st | (1 << i)][ra - needA + getA]){q.push(updatastatus(st | (1 << i),ra - needA + getA));arrived[st | (1 << i)][ra - needA + getA] = true;} }else //金夠銀不夠 {if (needB- rb <= rc){updata(st | (1 << i) , ra - needA + getA, rc - needB + rb + getC);if (!arrived[st | (1 << i)][ra - needA + getA]){q.push(updatastatus(st | (1 << i),ra - needA + getA));arrived[st | (1 << i)][ra - needA + getA] = true;} }}}else{if (rb >= needB) //金不夠銀夠 {if (needA - ra <= rc){updata(st | (1 << i) , getA, rc - needA + ra + getC);if (!arrived[st | (1 << i)][getA]){q.push(updatastatus(st | (1 << i),getA));arrived[st | (1 << i)][getA] = true;} }}else //金不夠銀不夠 {if (needA - ra + needB - rb <= rc){updata(st | (1 << i) , getA, rc - needA + ra - needB + rb + getC);if (!arrived[st | (1 << i)][getA]){q.push(updatastatus(st | (1 << i),getA));arrived[st | (1 << i)][getA] = true;} } } }}}}printf("%d\n",ans);return 0; }?
轉載于:https://www.cnblogs.com/Xiper/p/4539658.html
總結
以上是生活随笔為你收集整理的UESTC_酱神寻宝 2015 UESTC Training for Dynamic ProgrammingProblem O的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 寒山问拾得
- 下一篇: 第二次冲刺 站立会议5