UVA 10306 e-Coins(完全背包: 二维限制条件)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1247

题意:

对于每个样例,先给定两个数n,m,分别表示有n种硬币,对于每一种硬币有两个价值,分别记做x,y,题目要求从中选择一些硬币,使得满足m*m=X*X+Y*Y, 其中X是选出的硬币的所有x价值的和,Y是所有选出的硬币的y价值的和,硬币有无数多个,现在要求的是,满足上述要求使用的最少的硬币数

分析:

硬币数量无限,这就是显然的完全背包问题. 做这类问题首先要搞清楚什么是限制条件, 什么是目标条件?

本题的限制条件是:  x价值与y价值.(它们值共同构成了限制值m)

本题的目标条件是: 使得所选硬币最少.

一般的完全背包状态设计都是用 dp[i][j]==x 表示当决策完前i个物品后, 限制条件正好==j时(或者不超过j时), 能得到的目标条件最优(可能要求最小或最大).

本来我是想用m作为j这维度的限制条件的,但是发现如果用m作为一维限制条件,那么你无法根据当前的m值和你当前选的物品来推出你上一次决策前的m’值. 所以本题需要用x和y两维限制条件来做. (其实就是加了个维度,没什么本质的变化)

状态设计: dp[k][i][j]==num 表示决策完前k种硬币后, 当前所有硬币的x价值和为i , 当前所有硬币的y价值和为j 时所需要的最少硬币数目为num.(由x价值和与
y价值和我们确定唯一的 m )

状态转移:

dp[k][i][j] = min( dp[k-1][i][j] , dp[k][i-x[k]][j-y[k]])

如何理解上述的状态转移方程呢?

首先来看dp[k][i][j], 它表示用前k中硬币构成 x价值和为i , y价值和为j 的方法数目. 那么:

1. 如果我们根本不用第k种硬币(只用前k-1种硬币即可),我们可以知道有dp[k-1][i][j]种方式可以(不用任何一个第k种硬币)构成x价值和为i , y价值和为j 的状态.

2. 如果我们至少用1个第k种硬币来构成目标状态, 那么我们可以知道有dp[k][i-x[k]][j-y[k]] 种方法能达成目的.

综上所述, dp[k][i][j] = min( dp[k-1][i][j] ,dp[k][i-x[k]][j-y[k]] )

初值为dp[0][0][0]=0 , 其他为INF(无穷大).

最终我们所求为 所有的dp[n][i][j]中满足 i*i+j*j==m*m 的最小值.

程序实现用的滚动数组, 所以dp只有[i][j]这两个维度.

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 1e8
const int maxn=300+5;

int n,m;//n为货币种数,m为需要达到的价值
int x[maxn],y[maxn];//对应每种货币的两个属性值
int dp[maxn][maxn];

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        //读输入+初始化
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&x[i],&y[i]);
        for(int i=0;i<maxn;i++)
            for(int j=0;j<maxn;j++)
                dp[i][j]=INF;
        dp[0][0]=0;

        //递推求解
        int ans=INF;
        for(int k=1;k<=n;k++)
        for(int i=x[k];i<maxn;i++)
        for(int j=y[k];j<maxn;j++)
        {
            dp[i][j] = min(dp[i][j], dp[i-x[k]][j-y[k]]+1);
            if(i*i+j*j==m*m) //这里如果加了 k==n 就WA 想想为什么?
                ans=min(ans, dp[i][j]);
        }

        //输出
        if(ans==INF) printf("not possible\n");
        else printf("%d\n",ans);

    }
    return 0;
}
时间: 2024-12-18 15:49:21

UVA 10306 e-Coins(完全背包: 二维限制条件)的相关文章

UVA 10306 e-Coins(全然背包: 二维限制条件)

option=com_onlinejudge&Itemid=8&page=show_problem&problem=1247">http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1247 题意: 对于每一个例子.先给定两个数n,m,分别表示有n种硬币,对于每一种硬币有两个价值.分别记做x,y,题目要求从中

UVA 10465 Homer Simpson(完全背包: 二维目标条件)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1406 题意: 有两种汉堡包(汉堡数量无限多),第一种吃一个需要花n分钟,第二种吃一个需要花m分钟. 现在你有t分钟的时间, 问你最少浪费几分钟不能吃汉堡(你每次要么完整的吃完一个汉堡,要么不吃). 当吃汉堡花费的时间达到最大时, 问你最多能吃几个汉堡? 分析: 本题的限制条件是: 总时间&l

HDU 2159 FATE(完全背包:二维限制条件)

http://acm.hdu.edu.cn/showproblem.php?pid=2159 题意: 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务.久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级.现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度.当忍耐度降到0或者0以下时,xhd就不会玩这游戏.xhd还说了他最多只杀s只怪.请问他能升掉这最后一级吗?(每个怪

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

分组背包+二维费用背包

题目:https://www.acwing.com/problem/ 分组背包问题描述是共有n组物品,每组物品你只能选一个,求最大价值 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=110; 6 struct node 7 { 8 int v,w; 9 }; 10 node wp[N]; 11 int n,m; 12

UVA 562 Dividing coins (01背包)

//平分硬币问题 //对sum/2进行01背包,sum-2*dp[sum/2] #include <iostream> #include <cstring> #include <algorithm> using namespace std; int value[100000],dp[100000]; int main() { int n,m,sum,sum1; cin>>n; while(n--) { cin>>m; sum=0; for(int

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

At the Department for Bills and Coins, an extension of today's monetary system has newly been proposed, in order to make it fit the new economy better. A number of new so called e-coins will be produced, which, in addition to having a value in the no

UVA 10306 (二维完全背包)

UVA 10306 题意:有种新货币,它的价值有两个值 x 和 y,有一种 e-modulus 值, 计算方式为 sqrt(X*X + Y*Y); 其中 X 和 Y 分别是所有货币 x 值的总和 和 y 值的总和,即 (x1 + x2 +... +xm)^2 + (y1 + y2 +...+ym)^2 = s^2;给出 e-modulus 的值 s , 每种货币的数量无限, 求满足 S 值的货币的最小数量. 输入:第一行输入 n , n 组测试:第二行 m , s :表示有 m 中货币,e-mo

hdu2159 FATE 二维的完全背包

//这题典型的二维背包问题,因为题目说了每种怪的数量无限 //先开始的时候我想定义一个三维的dp,dp[i][j][k]表示前i种 //怪杀死j只剩余耐久点为dp[i][j][k]经验的最大值,然后状态 //方程就可以得到为dp[i][j][k] = max (dp[i-1][j][k],dp[i][j-1][k-b[i]]+a[i]); //这和完全背包的方程同出一辙,只是最后的答案我却不太清楚怎么找大, //最后看了一下题解,原来我的想法是对的,但最终的结果只要找到满足条件的最大的j就可以啦