题目链接: http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=774&pid=1003
题目大意: a[i], b[i] | 0 <= i <= n .................... k[j], p[j] | 0 <= j <= m, n个魔王, m中法术方式, 每个法术攻击p[j], 消耗k[j]水晶, 每个魔王a[i]生命, b[i]护甲, 攻击必须先打穿护甲, 求杀死所有魔王的最少水晶数。
解题思路: dp[i][j] 表示一个魔王血量为i 护甲为 j 的时候, 杀死它需要的最少水晶, 哦对了, 水晶无限, 所以就转换成n个完全背包问题, 再加和。
代码: 下面我的代码有错, 不知道哪儿错了
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <map> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <map> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 const int maxn = 1e5+100; const int maxm = 1e3 + 100; const int maxa = 1e3 + 100; const int maxb = 15; using namespace std; const int INF = 0x3fffffff; int a[maxn]; int b[maxn]; int k[maxm]; int p[maxm]; int dp[maxa][maxb]; // dp(i, j)生命值为i , 防御值为 j 的时候消灭它花费最少 int main() { int n, m; while( scanf( "%d%d", &n, &m ) == 2 ) { int defend = 0; int attack = 0; int ma = 0; for( int i = 1; i <= n; i++ ) { scanf( "%d%d", a+i, b+i ); defend = max( defend, *(b+i) ); ma = max( ma, *(a+i) ); } for( int i = 1; i <= m; i++ ) { scanf( "%d%d", k+i, p+i ); attack = max( attack, *(p+i) ); } if( attack <= defend ) { printf( "-1\n" ); continue; } for( int i = 0; i <= ma; i++ ) { for( int j = 0; j <= defend; j++ ) { if( i == 0 ) dp[0][j] = 0; else dp[i][j] = INF; } } for( int i = 1; i <= ma; i++ ) { for( int j = 0; j <= defend; j++ ) { for( int t = 1; t <= m; t++ ) { if( j > p[t] ) continue; else if( i - (p[t]-j) >= 0 ) { dp[i][j] = min( dp[i][j], dp[i-(p[t]-j)][j]+k[t] ); } else dp[i][j] = min( dp[i][j], dp[0][j]+k[t] ); } } } long long res = 0; for( int i = 1; i <= n; i++ ) { res += dp[a[i]][b[i]]; } printf( "%lld\n", res ); } return 0; }