Inviting Friends HDU - 3244

原题链接
考察:二分+完全背包
错误思路:
  说实话一眼看就觉得像背包,但是1e7的空间真的有点离谱,实际证明就是要敢想.后面想的贪心都贪不到最优解,枚举会超时.
思路:
  \(f[i][j]\)表示前\(i\)件物品,价值最少是j的最小花费.

\[f[i][j] = min(f[i-1][j],f[i][j-s[k]]+p[k]) \]

  二分,再套板子即可.
时间复杂度:\(O(17*2*10^7)\),感觉还是有可能超时啊...

Code

#include <iostream>
#include <cstring> 
using namespace std;
const int N = 110,M = 10000010;
int n,m,x[N],y[N],s[3][N],p[3][N],f[M];
bool check(int w)
{
    int sum = 0;
    for (int i = 1; i <= n;i++)
    {
        int ss = x[i] * w-y[i];
        if(ss<=0)
            continue;
        for(int k=1;k<=ss;k++) f[k] = 0x3f3f3f3f;
        f[0] = 0;
        for(int j=1;j<=2;j++)
          for(int k=0;k<=ss;k++)
            f[k] = min(f[k],f[max(k-s[j][i],0)]+p[j][i]);
        sum+=f[ss];
        if(sum>m) return 0;
    }
    return 1;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF&&(m+n))
    {
        for (int i = 1; i <= n;i++)
            scanf("%d%d%d%d%d%d", &x[i], &y[i], &s[1][i], &p[1][i], &s[2][i], &p[2][i]);
        int l = 0, r = 100100;
        while(l<r)
        {
            int mid = l + r + 1 >> 1;
            if(check(mid))
                l = mid;
            else
                r = mid - 1;
        }
        printf("%d\n", r);
    }
    return 0;
}
posted @ 2021-07-07 23:24  acmloser  阅读(31)  评论(0编辑  收藏  举报