腾讯机试题 AcWing 603 打怪兽
Posted zaq19970105
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了腾讯机试题 AcWing 603 打怪兽相关的知识,希望对你有一定的参考价值。
题目链接:https://www.acwing.com/problem/content/605/
题目大意:
略
分析:
用dp[i][j]表示用j元钱能在前i只怪兽上所能贿赂到的最大武力值。
有一种情况就是打到第i只怪兽所需的最低花费大于j,那么令dp[i][j] = -1。
那么dp[i + 1][j],也就是同样用j元钱能在前i + 1只怪兽上所能贿赂到的最大武力值是多少呢?有3种情况:
1:dp[i][j] = -1,显然dp[i + 1][j] = -1。
2:dp[i][j] < d[i + 1],也就是用j元钱在前i只怪兽上所能贿赂到的最大武力值都没有第i+1只怪兽的武力值大,这个时候必须腾出p[i + 1]元来贿赂第i + 1只怪兽,此时又有3种小情况:
(1):j < p[i + 1],这就没的说了,钱不够,直接dp[i + 1][j] = -1。
(2):dp[i][j - p[i + 1]] == -1,这说明腾不出钱来,于是dp[i + 1][j] = -1。
(3):dp[i][j - p[i + 1]] != -1,那么dp[i + 1][j] = dp[i][j - p[i + 1]] + d[i + 1],不存在选择,必须贿赂。
3:dp[i][j] >= d[i + 1],在这种情况下可以选择贿赂,也可以选择不贿赂,两种情况取最大即可,dp[i + 1][j] = max(dp[i][j], dp[i][j - p[i + 1]] + d[i + 1])。
递推关系有了,现在需要第0列的初始值:除了第0行,其他全部为-1;和第0行的初始值:全部为0。
那dp数组算出来了有啥用呢?
假设你打到第i个怪的时候,武力值为D,这时D < d[i],那你就在dp数组第i行找第一个使得dp[i][j] >= d[i]的j,这个j一定是打前i个怪最优的,因为花费比j小的金钱过不了这个boss,如果这个j能一直保持到游戏结束,那这个j就是总体最优的。
代码如下:
1 #pragma GCC optimize("Ofast") 2 #include <bits/stdc++.h> 3 using namespace std; 4 5 #define INIT() std::ios::sync_with_stdio(false);std::cin.tie(0); 6 #define Rep(i,n) for (int i = 0; i < (n); ++i) 7 #define For(i,s,t) for (int i = (s); i <= (t); ++i) 8 #define rFor(i,t,s) for (int i = (t); i >= (s); --i) 9 #define ForLL(i, s, t) for (LL i = LL(s); i <= LL(t); ++i) 10 #define rForLL(i, t, s) for (LL i = LL(t); i >= LL(s); --i) 11 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i) 12 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i) 13 14 #define pr(x) cout << #x << " = " << x << " " 15 #define prln(x) cout << #x << " = " << x << endl 16 #define EL() printf(" ") 17 18 #define SORT(c, s, t) sort(c + s, c + t + 1) 19 20 #define LOWBIT(x) ((x)&(-x)) 21 22 #define ALL(x) x.begin(),x.end() 23 #define INS(x) inserter(x,x.begin()) 24 25 #define ms0(a) memset(a,0,sizeof(a)) 26 #define msI(a) memset(a,inf,sizeof(a)) 27 #define msM(a) memset(a,-1,sizeof(a)) 28 29 #define pii pair<int,int> 30 #define piii pair<pair<int,int>,int> 31 #define MP make_pair 32 #define PB push_back 33 #define ft first 34 #define sd second 35 36 template<typename T1, typename T2> 37 istream &operator>>(istream &in, pair<T1, T2> &p) { 38 in >> p.first >> p.second; 39 return in; 40 } 41 42 template<typename T> 43 istream &operator>>(istream &in, vector<T> &v) { 44 for (auto &x: v) 45 in >> x; 46 return in; 47 } 48 49 template<typename T1, typename T2> 50 ostream &operator<<(ostream &out, const std::pair<T1, T2> &p) { 51 out << "[" << p.first << ", " << p.second << "]" << " "; 52 return out; 53 } 54 55 typedef long long LL; 56 typedef unsigned long long uLL; 57 typedef pair< double, double > PDD; 58 typedef set< int > SI; 59 typedef vector< int > VI; 60 const double EPS = 1e-10; 61 const int inf = 1e9 + 9; 62 const LL mod = 1e9 + 7; 63 const int maxN = 1e5 + 7; 64 const LL ONE = 1; 65 66 //! n 表示怪兽的数量 67 //! d[i] 表示第i只怪兽的武力值 68 //! p[i] 表示收买第i只怪兽所需的金币数 69 //! ans 最小花费 70 int n, p[57], ans; 71 LL d[57]; 72 //! dp[i][j] 表示用j元钱能在前i只怪兽上所能贿赂到的最大武力值 73 LL dp[57][107]; 74 75 76 int main(){ 77 INIT(); 78 cin >> n; 79 For(i, 1, n) cin >> d[i]; 80 For(i, 1, n) cin >> p[i]; 81 82 For(i, 1, n) dp[i][0] = -1; 83 84 For(j, 1, 2 * n) { 85 For(i, 1, n) { 86 if(dp[i - 1][j] == -1) dp[i][j] = -1; 87 else if(dp[i - 1][j] < d[i]) { 88 if(j < p[i]) dp[i][j] = -1; 89 else if(dp[i - 1][j - p[i]] == -1) dp[i][j] = -1; 90 else dp[i][j] = dp[i - 1][j - p[i]] + d[i]; 91 } 92 else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - p[i]] + d[i]); 93 } 94 } 95 96 // maxD 最大武力值 97 // maxDi 最大武力值下标 98 LL maxD = -1, maxDi; 99 For(i, 1, n) { 100 if(d[i] > maxD) { 101 maxD = d[i]; 102 maxDi = i; 103 } 104 } 105 106 ans = lower_bound(dp[maxDi], dp[maxDi] + 2 * n, maxD) - dp[maxDi]; 107 108 cout << ans << endl; 109 return 0; 110 }
以上是关于腾讯机试题 AcWing 603 打怪兽的主要内容,如果未能解决你的问题,请参考以下文章