uva 10280 完全背包+剪枝

来源:互联网 发布:linux 进程 流量 编辑:程序博客网 时间:2024/06/06 07:27

题意:

L升酒,n个酒瓶子, 每个酒瓶子有最小容量和最大容量并且有无限个。

问最多剩多少酒没有装进去。


解析:

这题的剪枝是在http://blog.csdn.net/yan_____/article/details/8671147这篇博客里学到的。

有点像一道蓝桥杯的题的剪枝,爬到最后越来越密集。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = 4 * atan(1.0);const double ee = exp(1.0);const int maxn = 100 + 10;const int maxv = 4500 + 10;const int maxs = 450000;int L, N;int lo[maxn], hi[maxn];int vis[maxv], v[maxv];int dp[maxs];int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    int ncase;    scanf("%d", &ncase);    while (ncase--)    {        scanf("%d%d", &L, &N);        L *= 1000;        int limit = inf;        for (int i = 0; i < N; i++)        {            scanf("%d%d", &lo[i], &hi[i]);            int t = (lo[i] * lo[i]) / (hi[i] - lo[i]);            if (t < limit)                limit = t;        }        if (limit < L)            printf("0\n");        else        {            int index = 0;            memset(vis, 0, sizeof(vis));            for (int i = 0; i < N; i++)            {                for (int j = lo[i]; j <= hi[i]; j++)                {                    if (!vis[j])                    {                        vis[j] = 1;                        v[index++] = j;                    }                }            }            memset(dp, 0, sizeof(dp));            for (int i = 0; i < index; i++)            {                for (int j = v[i]; j <= L; j++)                {                    int t = dp[j - v[i]] + v[i];                    if (dp[j] < t)                        dp[j] = t;                }            }            printf("%d\n", L - dp[L]);        }        if (ncase)            printf("\n");    }    return 0;}


0 0