一道动归的水题
一开始AC的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define MIN(A,B) (A<B?A:B)
#define LEN 10001
#define MMAX 0x3f3f3f3f
int dp[LEN], mark[LEN];
int main() {
int t, e, f;
int n;
int p, w;
scanf("%d", &t);
while(t--) {
int i, j, tail;
scanf("%d%d%d", &e, &f, &n);
for(i = 0; i < LEN; i++) {
dp[i] = MMAX;
}
memset(mark, 0, sizeof(mark));
mark[0] = 1;
dp[0] = 0;
tail = f-e;
for(i = 0; i < n; i++) {
scanf("%d%d", &p, &w);
for(j = w; j <= tail; j++) {
if(1 == mark[j-w]) {
dp[j] = MIN(dp[j], dp[j-w]+p);
mark[j] = 1;
}
}
}
if(MMAX == dp[tail]) {
printf("This is impossible.\n");
}
else {
printf("The minimum amount of money in the piggy-bank is %d.\n", dp[tail]);
}
}
return 0;
}
后来发现其实不加 if(1 == mark[j-w]) 这个判断也能过,因为当他没有被计算过的时候,dp的值就是MMAX,也就会忽略 dp[j] 的大小。
改进后:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define MIN(A,B) (A<B?A:B)
#define LEN 10001
#define MMAX 0x3f3f3f3f
int dp[LEN], mark[LEN];
int main() {
int t, e, f;
int n;
int p, w;
scanf("%d", &t);
while(t--) {
int i, j, tail;
scanf("%d%d%d", &e, &f, &n);
for(i = 0; i < LEN; i++) {
dp[i] = MMAX;
}
memset(mark, 0, sizeof(mark));
mark[0] = 1;
dp[0] = 0;
tail = f-e;
for(i = 0; i < n; i++) {
scanf("%d%d", &p, &w);
for(j = w; j <= tail; j++) {
// if(1 == mark[j-w]) {
dp[j] = MIN(dp[j], dp[j-w]+p);
// mark[j] = 1;
// }
}
}
if(MMAX == dp[tail]) {
printf("This is impossible.\n");
}
else {
printf("The minimum amount of money in the piggy-bank is %d.\n", dp[tail]);
}
}
return 0;
}