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;

}

你可能感兴趣的:(uva)