您的位置:首页 > 其它

poj 1276

2016-07-25 16:34 211 查看

题目概述

一个ATM机里有多种面额不同的货币,每种储量不同,有人要取钱时,会吐出尽可能多但不超过要取钱数的钱,给出要取钱数request,货币种数N,货币面额deno及储量num,问最多会吐出多少钱

时限

1000ms/3000ms

输入

每行第一个整数request,第二个整数N,其后2*N个整数 分别为num和deno,输入到EOF结束

限制

0<=N<=10;0<=num<=1000;1<=deno<=1000;0<=request<=100000

输出

每行一个数,ATM最多会吐出的钱数

样例输入

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

讨论

dp,不过看上去当背包能更好做,只要把面额同时当成价值和体积就可以,几乎算是模版题了,也懒得多去改进代码了

题解状态

568K,63MS,C++,1232B

题解代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 1003
#define memset0(a) memset(a,0,sizeof(a))
#define EPS 1e-6

int request, N, dp[100003], denos[MAXN], nums[MAXN];//取款数 货币种数 dp辅助数组 denomination 面额 数量
int fun()
{
for (int p = 0; p < N; p++)
scanf("%d%d", &nums[p], &denos[p]);//input
for (int p = 0; p < N; p++) {
if (nums[p] * denos[p]>request) {//完全背包
for (int i = 0; i <= request; i++) {
dp[i] = max(dp[i], i - denos[p] >= 0 ? (dp[i - denos[p]] + denos[p]>request ? -INF : dp[i - denos[p]] + denos[p]) : -INF);//这么复杂只是包含了2个?:算符 一个处理是否越界 一个处理是否超过取款数
}
}
else {//01背包 外带二进制优化
for (int i = 1; i <= nums[p]; i <<= 1) {
for (int u = request; u >= denos[p] * i; u--) {
dp[u] = max(dp[u], dp[u - denos[p] * i] + denos[p] * i > request ? -INF : dp[u - denos[p] * i] + denos[p] * i);//一定不会越界
}
nums[p] -= i;
}
for (int i = request; i >= denos[p] * nums[p]; i--) {
dp[i] = max(dp[i], dp[i - denos[p] * nums[p]] + denos[p] * nums[p] > request ? -INF : dp[i - denos[p] * nums[p]] + denos[p] * nums[p]);//也是两个?:算符
}
}
}
return dp[request];
}
int main(void)
{
//freopen("vs_cin.txt", "r", stdin);
//freopen("vs_cout.txt", "w", stdout);

while (~scanf("%d%d", &request, &N)) {//input
printf("%d\n", fun());//output
memset0(dp);
}
}


EOF
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: