Climber.pI的OI之路

Through the darkest dark,may we see the light.

USACO 4.1.1 Nuggets

重启usaco.

抽象出模型,可以发现是一个简单的完全背包问题,复杂度O(N^2+VN).需要考虑几种特殊情况:
(1)无解
当且仅当n个数中有一个数为1.
(2)惟一解
需要确定的是体积v的最大值.题解中是最大的两个数的最小公倍数,程序中使用最大数的平方,证明方法不知.
(3)无限解
n个数不互质

 1/*
 2ID: liuyupa1
 3PROG: nuggets
 4LANG: C++
 5*/

 6#include<stdio.h>
 7int w[15] = {0}, f[66000] = {0};
 8int p[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251};
 9void swap(int *x, int *y){
10    int k = *x; *x = *y; *y = k;
11}

12int max(int x, int y){
13    return x>y ? x : y;
14}

15int main(){
16    FILE *fin, *fout;
17    fin = fopen("nuggets.in", "r");
18    fout = fopen("nuggets.out", "w");
19    int n, i, j;
20    fscanf(fin, "%d", &n);
21    for (i = 1; i <= n; i++) fscanf(fin, "%d", &w[i]);
22    for (j = 0; j < 54; j++){
23        int t = 0;
24            for (i = 1; i <= n; i++)
25            if (w[i] % p[j] == 0) t++;
26        if (t == n) {
27            fprintf(fout, "0\n", p[j]);
28            return 0;
29        }

30    }

31    for (i = 1; i < n; i++)
32        for (j = i+1; j <= n; j++)
33            if (w[i] > w[j]) swap(&w[i], &w[j]);
34    if (w[1] == 1){
35        fprintf(fout, "0\n", p[j]);
36        return 0;
37    }

38    for (i = 1; i <= n; i++)
39        for (j = 0; j <= w[n]*w[n]; j++)
40            if (j-w[i] >= 0)
41                f[j] = max(f[j], f[j-w[i]]+w[i]);
42    i = w[n-1]*w[n];
43    while (i > -1 && f[i] == i) i--;
44    fprintf(fout, "%d\n", i);
45    return 0;
46}

47

posted on 2010-10-19 17:05 Climber.pI 阅读(354) 评论(0)  编辑 收藏 引用 所属分类: 动态规划