UVa 10280 Old Wine Into New Bottles(剪枝+完全背包)
题意:
给L升酒,有n个酒瓶,每个酒瓶有个最大容量和最小容量,酒瓶的个数不限。
问最多剩多少毫升酒没有装进去。
思路:
http://www.cnblogs.com/staginner/archive/2011/12/07/2279783.html
这一题用到了一个优化的剪枝,另外上面博客对于物品的处理也是非常得当。
做完题目之后如沐清风,回味无穷。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <algorithm>
using namespace std;
const int MAXL = 450000;
const int MAXD = 4600;
const int MAXN = 110;
int dp[MAXL], v[MAXD];
bool vis[MAXD];
int cmax[MAXN], cmin[MAXN];
int L, n;
int solve()
{
int limit = INT_MAX;
for (int i = 0; i < n; ++i)
limit = min(limit, cmin[i]*cmin[i]/(cmax[i]-cmin[i]));
if (limit < L)
return 0;
int m = 0;
memset(vis, false, sizeof(vis));
for (int i = 0; i < n; ++i)
for (int j = cmin[i]; j <= cmax[i]; ++j)
if (!vis[j])
vis[j] = true, v[m++] = j;
memset(dp, 0, sizeof(dp));
for (int i = 0; i < m; ++i)
for (int j = v[i]; j <= L; ++j)
dp[j] = max(dp[j], dp[j-v[i]] + v[i]);
return L - dp[L];
}
int main()
{
int cases;
scanf("%d", &cases);
while (cases--)
{
scanf("%d %d", &L, &n);
L *= 1000;
for (int i = 0; i < n; ++i)
scanf("%d %d", &cmin[i], &cmax[i]);
printf("%d\n", solve());
if (cases)
printf("\n");
}
return 0;
}
-------------------------------------------------------
kedebug
Department of Computer Science and Engineering,
Shanghai Jiao Tong University
E-mail: kedebug0@gmail.com
GitHub: http://github.com/kedebug
-------------------------------------------------------