题目大意:有一只boss,血量为L
你有N招技能,每招技能都有相应的蓄能时间,释放后,能每秒造成K点伤害
问至少需要几秒才能干掉boss
解题思路:我能说这题我是用bfs解决的吗 。。。
用dp[i][j]表示在第j秒,造成的伤害为i时,每秒能造成的伤害
参考了一下别人的,神奇的思路:
用dp[i + time[j]]表示在 i + time[j] 这个时刻所能造成的总伤害的最大值
转移方程为dp[i + time[j]] = max(dp[i + time[j]], dp[i] + l[j] * i)
time表示造船时间,l表示造成的持续伤害
这个转移方程表示的是,用i + time[j]这段时间的0-time[j]这段时间造了第j艘船,然后这艘船在总时间内造成的伤害就有i * l[j]了
因为还有i这段时间,i这段时间所造成的伤害就是dp[i]了
所以就有上述的转移方程了
BFS解法:卡时间过的 所以提交的时候不一定会A了,有可能TLE
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 350;
const int INF = 0x3f3f3f3f;
struct Ship{
int t, l;
}S[35];
struct Node {
int des, time;
Node() {}
Node(int des, int t): des(des), time(t) {}
};
int n, l;
int dp[N][N];
void init() {
for (int i = 0; i < n; i++)
scanf("%d%d", &S[i].t, &S[i].l);
}
void solve() {
memset(dp, 0, sizeof(dp));
queue<Node> Q;
Q.push(Node(0, 0));
int ans = INF;
while (!Q.empty()) {
Node t = Q.front(); Q.pop();
if (dp[t.des][t.time]) {
int used = (l - t.des) / dp[t.des][t.time];
if ((l - t.des) % dp[t.des][t.time]) used++;
ans = min(t.time + used, ans);
}
for (int i = 0; i < n; i++) {
int des = t.des + ( dp[t.des][t.time] * S[i].t);
int time = t.time + S[i].t;
if (des >= l) {
ans = min(ans, time);
continue;
}
if (des >= N || time >= N) continue;
if (dp[t.des][t.time] + S[i].l > dp[des][time]) {
dp[des][time] = dp[t.des][t.time] + S[i].l;
Q.push(Node(des, time));
}
}
}
printf("%d\n", ans );
}
int main() {
while (scanf("%d%d", &n, &l) != EOF) {
init();
solve();
}
return 0;
}
背包解法:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 333;
int t[N], l[N], dp[N];
int n, m;
void init() {
for (int i = 0; i < n; i++)
scanf("%d%d", &t[i], &l[i]);
}
void solve() {
memset(dp, 0, sizeof(dp));
for (int i = 0; i < 333; i++)
for (int j = 0; j < n; j++)
if (i + t[j] < 333)
dp[i + t[j]] = max(dp[i + t[j]], dp[i] + l[j] * i);
for (int i = 0; i < 333; i++)
if(dp[i] >= m) {
printf("%d\n", i);
return ;
}
}
int main() {
while (scanf("%d%d", &n, &m) != EOF ) {
init();
solve();
}
return 0;
}