UVa 10306 e-Coins(二维完全背包)

题目:

有n种物品,每种物品有x, y两个价值,并且可以有无限多个。

给定s,使得(x1+x2+....)^2 + (y1+y2+....)^2 = s ^ 2。并且物品个数最少。

思路:

既然是物品个数没有限制,则就要想到完全背包。但是此时如何背包就要退而求解。

dp[i][j] 表示能选到x的总和为i,y的总和为j时,最少的物品选择数。

此时还有个隐性的物品背包属性,那就是个数:把物品的价值当作是背包容量,个数当作是价值。求能达到要求且价值最小的情况。

初始化状态:dp[0][0] = 0。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>

#define min(a,b) (((a) < (b)) ? (a) : (b))

const int MAXN = 301;
int dp[MAXN][MAXN];     
int w1[50], w2[50];

int main()
{
    int cases;
    scanf("%d", &cases);
    while (cases--)
    {
        int m, S;
        scanf("%d %d", &m, &S);

        for (int i = 0; i < m; ++i)
            scanf("%d %d", &w1[i], &w2[i]);
        
        for (int i = 0; i <= S; ++i)
            for (int j = 0; j <=S; ++j)
                dp[i][j] = INT_MAX;
        dp[0][0] = 0;

        for (int i = 0; i < m; ++i)
            for (int v1 = w1[i]; v1 <= S; ++v1)
                for (int v2 = w2[i]; v2 <= S; ++v2)
                    if (dp[v1-w1[i]][v2-w2[i]] != INT_MAX)
                        dp[v1][v2] = min(dp[v1][v2], dp[v1-w1[i]][v2-w2[i]] + 1);

        int ans = INT_MAX;
        int t = S * S;
        for (int i = 0; i <= S; ++i)
            for (int j = 0; j <= S; ++j)
                if (i * i + j * j == t && dp[i][j] != INT_MAX)
                    if (ans > dp[i][j])
                        ans = dp[i][j];

        if (ans != INT_MAX)
            printf("%d\n", ans);
        else
            printf("not possible\n");
    }
    return 0;
}
posted @ 2012-11-19 13:31  kedebug  阅读(713)  评论(0编辑  收藏  举报