您的位置:首页 > Web前端

poj 3260 The Fewest Coins 多重背包+完全背包

2015-02-19 12:08 441 查看
题目链接:http://poj.org/problem?id=3260

给店家的钱是多重背包 dp[]

店家的找钱是完全背包 dp2[]

然后最后 其中i表示多给了多少钱 也就是需要找回多少钱

int ans = INF;

ans = min(ans, dp[m+i] + dp2[i]);

是一个比较简单的思路

神坑题

看到每种货币的面值不大于120 我就觉得找钱一定不会超过119块钱结果wa到死

后来才发现不是的啊

之所以我有这种思维定式是因为现实生活中有1块钱这种货币单位

考虑一种极限的情况

只有面值为120元、119元两种货币

然后你只有120那种 要去买价值为120*82 + 119 = 9959元的东西

那119的部分需要你给店家119张120块钱让他找你119张119块钱Orz 【三观啊...

这样一来可以大概估计找钱的一个上界是14400

所以两个DP过程的容量都加上14400然后再去做就能过T^T

另外写CompletePack2()的时候我明明没有改V的值可是V的值变了

后来才反应过来这种事情很可能就是数组越界

检查了一下果然边界情况没有控制好

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <set>
#include <queue>
#include <vector>

using namespace std;

typedef long long ll;

const int maxn = 110;
const int maxm = 10200;
const int INF = 100000;

int a[maxn], c[maxn];
int dp[maxm + 15000];
int dp2[15000];
int V;

void ZeroOnePack(int cost, int weight)
{
for(int i = V; i >= cost; i--)
{
dp[i] = min(dp[i], dp[i-cost] + weight);
}
}

void CompletePack(int cost, int weight)
{
for(int i = cost; i <= V; i++)
{
dp[i] = min(dp[i], dp[i-cost] + weight);
}
}

void MultiplePack(int cost, int weight, int amount)
{
if(cost*amount >= V)
{
CompletePack(cost, weight);
return;
}
int k = 1;
while(k < amount)
{
ZeroOnePack(k*cost, k*weight);
amount = amount - k;
k *= 2;
}
ZeroOnePack(amount*cost, amount*weight);
}

void CompletePack2(int cost, int weight)
{
for(int i = cost; i < V; i++)
{
dp2[i] = min(dp2[i], dp2[i-cost] + weight);
}
}

int main()
{
//freopen("in.txt", "r", stdin);

int n, m;

while(scanf("%d%d", &n, &m) == 2)
{
memset(dp, 0x3f, sizeof(dp));
memset(dp2, 0x3f, sizeof(dp2));
dp[0] = dp2[0] = 0;

for(int i = 0; i < n; i++)
scanf("%d", &a[i]);

for(int i = 0; i < n; i++)
scanf("%d", &c[i]);

V = m + 14400;
for(int i = 0; i < n; i++)
MultiplePack(a[i], 1, c[i]);

V = 14400;
for(int i = 0; i < n; i++)
{
CompletePack2(a[i], 1);
}

int ans = INF;
for(int i = 0; i < 14400; i++)
{
ans = min(ans, dp[m+i] + dp2[i]);
}

if(ans == INF)
printf("-1\n");
else
printf("%d\n", ans);
}

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