题意:
求不大于所给金额且不超过所给面额的数量限制之下的,最大金额
所给金额不超10w,所给面额不过10种,每种面额不超1000张
val[]金额, n[]数量;
思路:
以前做过一遍,是多重背包的变形,dp[i]表示如果能达到i面额dp[i]就赋值1,否则为0
代码:
/**************************************************************
Problem: poj_1276
User: soundwave
Language: C++
Result: Accepted
Time: 563ms
Memory: 1052KB
****************************************************************/
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn=15;
const int maxm=100000+5;
int n[maxn], val[maxn];
int dp[maxm];//dp[i] 如果到达i面额就赋值1,背包的变形
int main(){
int cash, N;
int tmp;
while(~scanf("%d%d", &cash, &N)){
memset(dp,0,sizeof(dp));
for(int i=0; i<N; i++)
scanf("%d%d", &n[i], &val[i]);
if(cash==0 || N==0){
printf("0\n");
continue;
}
dp[0]=1;
for(int i=0; i<N; i++)
for(int j=cash; j>=0; j--)
if(dp[j]){
for(int k=1; k<=n[i]; k++){
tmp = j+k*val[i];
if(tmp>cash) break;
dp[tmp] = 1;
}
}
for(int i=cash; i>=0; i--)
if(dp[i]){
printf("%d\n", i);
break;
}
}
return 0;
}
/*
735 3 4 125 6 5 3 350
633 4 500 30 6 100 1 5 0 1
735 0
0 3 10 100 10 50 10 10
--------------------------------
735
630
0
0
*/
反思:
翻了以前的记录,发现当时有种错误的思路,也写一下:
给出状态转移方程:f[i][v] = max{f[i-1][v-k*w[i]] + k}, 0<=k<=n[i];
前i种面额恰好填满v金额的最小数,不管是最小数还是最大数,只要这个数存在,找到距所给金额最接近的数即可
思维比较混乱,以至于这个思路无法继续下去,只好换成上面AC代码的思路