ZOJ - 3623 Battle Ships(完全背包或者BFS)

题目大意:有一只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 
#include 
#include 
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 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 
#include 
#include 
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;
}

你可能感兴趣的:(ACM-动态规划-背包)