2012-12-27 15:50:15Morris

[UVA][dp] 12589 - Learning Vector

題目意思:從 N 個向量挑出 K 個,然後從 (0,0) 開始加,與 X 軸圍成的最大面積為何?

解法:
很明顯地,假使全部都選,肯定是形成一個凸多邊形,如果不是,把他調成凸多邊形一定更大。
由於只能挑 K 個,我們先將斜率由大排到小。
然後使用 dp[使用 i 個向量][目前高度] = 最大面積 動規之。

特別感謝 inker


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct vec {
    int x, y;
};
bool cmp(vec a, vec b) {
    return b.x*a.y > b.y*a.x;
}
int main() {
    int t, cases = 0, n, m;
    int i, j, k;
    scanf("%d", &t);
    while(t--) {
        scanf("%d %d", &n, &m);
        vec V[55];
        int sumh = 0;
        for(i = 0; i < n; i++) {
            scanf("%d %d", &V[i].x, &V[i].y);
            sumh += V[i].y;
        }
        sort(V, V+n, cmp);
        int dp[m+1][sumh+1], dph[m+1];
        memset(dp, 0, sizeof(dp));
        memset(dph, 0, sizeof(dph));
        dp[0][0] = 1;
        int ans = 0;
        for(i = 0; i < n; i++) {
            for(j = min(m-1, i); j >= 0; j--) {
                for(k = min(dph[j], sumh-V[i].y); k >= 0; k--) {
                    if(dp[j][k]) {
                        dp[j+1][k+V[i].y] = max(dp[j+1][k+V[i].y], dp[j][k]+(2*k+V[i].y)*V[i].x);
                        dph[j+1] = max(dph[j+1], k+V[i].y);
                    }
                }
            }
        }
        for(i = 0; i <= sumh; i++)
            ans = max(ans, dp[m][i]);
        printf("Case %d: %d\n", ++cases, ans-1);
    }
    return 0;
}