xjoi题解:P7698 小信打怪
时间:1s 空间:256M
题目描述:
小信在游戏中遇到了怪物,并想要攻击力恰好等于它的血量n,打倒它。他的初始攻击力为0,可以通过下面四种道具改变攻击力,购买道具需要一定的金币:
将攻击力变为当前的 2 倍需要 i 金币。
将攻击力变为当前的 3 倍需要 j 金币。
将攻击力变为当前的 5 倍需要 k 金币。
将攻击力加 1 或减 1 需要 l 金币。
可以按任意顺序使用道具,并且道具的数量无限,小信最少要花多少金币才能恰好打倒怪物?
输入格式:
第一行包含整数 T ,表示测试用例数。
接下来 T 行,每行包含五个整数 n,i,j,k,l 。
输出格式:
对于每个测试用例,输出一行表示答案。
样例1输入:
4
6 2 5 10 1
6 3 5 10 2
6 1000000000 1000000000 1 1000000000
1145141919810 114 514 1919 810
样例1输出:
5
9
2000000001
11202
约定与提示:
对于100%的数据,1 ≤ T ≤ 10,1 ≤ n ≤ 10181 ≤ i, j, k, l ≤ 109
样例的第一个case:先花费 3 金币使用第 4 种道具将攻击增加到 3,再花费 2 金币使用第 1 种道具将攻击乘以 2。
样例的第二个case:先花费 4 金币使用第 4 种道具将攻击增加到 2,再花费 5 金币使用第 2 种道具将攻击乘以 3。
题意:
你有四种决策,分别是*2,*3,*5,+-1,每种决策都有相对应的代价,问如何运用这些决策,将0刚好凑到n的做小代价和
分析:
我们要运用正难则反的思路,既然我们要将0运用四种决策凑到n,那么我们就可以反过来想,将n减少到0(运用/2,/3,/5,+-1),这样就简单很多。其实有六种变化方式,就是将n加或减到能被3种整除方式整除,显然在加减过程中就包含+-1的这种决策,当然我们也要考虑一直减或加的方式。所以还是一道dfs题啦,将六种情况罗列出来就行啦。
题解:
#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long
int n, I, J, K, L, T;
map<int , int >f;
int dfs(int n) {
if (n == 1)return L;
if (n == 0)return 0;
if (f.count(n))return f[n];
int x = n * L;
x = min(x, dfs(n / 2) + I + n % 2 * L);
x = min(x, dfs((n + 1) / 2) + I + n % 2 * L);
x = min(x, dfs(n / 3) + J + (n - n / 3 * 3) * L);
x = min(x, dfs((n + 2) / 3) + J + ((n + 2) / 3 * 3 - n) * L);
x = min(x, dfs(n / 5) + K + (n - n / 5 * 5) * L);
x = min(x, dfs((n + 4) / 5) + K + ((n + 4) / 5 * 5 - n) * L);
return f[n] = x;
}
signed main() {
cin >> T;
while (T--) {
cin>>n>>I>>J>>K>>L;
f.clear();
cout << dfs(n) << endl;
}
}