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

2015-01-27 14:18:36 · 作者: · 浏览: 21

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

?

对于每个样例,先给定两个数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
  
   
#include
   
     #include
    
      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
     
      

?