vijos 猫狗大战

来源:互联网 发布:免费手机炒股软件排行 编辑:程序博客网 时间:2024/04/29 18:25


倒不是这道题多难

记下来作为警告。。。


这道题是个普通背包问题

我一开始相差了

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#define N 210#define INF 987654321using namespace std;int main() {    int n;    while(scanf("%d", &n) != EOF) {        int a[N], sum = 0, dp[8100];        for(int i = 0; i < n; i++) {            scanf("%d", &a[i]);            sum += a[i];        }        for(int i = 0; i < n; i++) {            for(int j = sum / 2; j >= a[i]; j--) dp[j] = max(dp[j], dp[j - a[i]] + a[i]);        }        if(dp[sum / 2] > sum - dp[sum / 2]) printf("%d %d\n", sum - dp[sum / 2], dp[sum / 2]);        else printf("%d %d\n", dp[sum / 2], sum - dp[sum / 2]);    }}

这忽略了一个条件  选取个数必须 n / 2 or n / 2 + 1

so ...

二维背包下  f[i][j] 前i个兵能否达到j血

最后再直接搜下f[n/2][i]   i <- sum / 2 to 0

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#define N 210#define INF 987654321using namespace std;int dp[N][8100];int main() {    int n;    while(scanf("%d", &n) != EOF) {        int a[N], sum = 0, ans = 0;        memset(dp, 0, sizeof(dp));        for(int i = 1; i <= n; i++) {            scanf("%d", &a[i]);            sum += a[i];            //dp[i][0] = 1;        }        dp[0][0] = 1;        for(int i = 1; i <= n; i++) {            for(int j = n / 2; j >= 1; j--)                for(int k = 8000; k >= 0; k--) if(dp[j - 1][k]) dp[j][k + a[i]] = 1;        }        for(int i = sum / 2; i >= 0; i--) if(dp[n / 2][i]) {            ans = i;            break;        }        if(ans > sum - ans) printf("%d %d\n", sum - ans, ans);        else printf("%d %d\n", ans, sum - ans);    }}

令我费解的是  dp[i][0] 存在就是错的 这是为何 后来突然想起。。 影响了前面的判断。。。 

归根结底原因还是没深刻理解清楚优化的原理