背包——AtCoder Regular Contest 073 #D

来源:互联网 发布:wp login.php 编辑:程序博客网 时间:2024/06/07 21:17
  • 题目链接:http://arc073.contest.atcoder.jp/tasks/arc073_b

  • 题意:01背包的题意,但是物品价值为1~1E7,物品质量为1~1E9,但是每个物品的质量范围为 [w1w1+3]

  • 分析: 虽然物品质量很大,但是都是在 [w1w1+3] 以内,所以我们很容易就能想到把 w1 都提取出来。那么原来01背包的状态是 DP[i][j] 表示前 i 个物品占 j 质量的时候的最大价值,因为第二维直接开物品质量开不了,所以现在就可以改成 DP[i][j][k] 表示前 i 个物品占kw1+j (kkjj300) 质量时的最大价值了。

  • 状态转移方程:

/*************************************************************************    > File Name: test.cpp    > Author: Akira     > Mail: qaq.febr2.qaq@gmail.com  ************************************************************************/#include<bits/stdc++.h>typedef long long LL;typedef unsigned long long ULL;typedef long double LD;#define MST(a,b) memset(a,b,sizeof(a))#define CLR(a) MST(a,0)#define Sqr(a) ((a)*(a))using namespace std;#define MaxN 110#define MaxM #define INF 0x3f3f3f3f#define PI 3.1415926535897932384626const int mod = 1E9+7;const double eps = 1e-6;#define bug cout<<88888888<<endl;#define debug(x) cout << #x" = " << x << endl;LL N,W;LL w[MaxN], v[MaxN];LL DP[MaxN][4*MaxN][MaxN];void solve(){    LL W1 = w[1];    for(int i=1;i<=N;i++) w[i] = w[i] - W1;    for(int i=1;i<=N;i++)    {        for(int j=0;j<=300;j++)        {            for(int k=1;k<=N;k++)            {                if( j >= w[i] )                     DP[i][j][k] = max( DP[i-1][j][k], DP[i-1][j-w[i]][k-1]+v[i]);                else                     DP[i][j][k] = DP[i-1][j][k];            }        }    }    LL ans = 0;    for(int j=0;j<=300;j++)    {        for(int k=0;k<=N;k++)        {            if( k*W1+j<=W)            {                ans = max(ans, DP[N][j][k]);            }        }    }    printf("%lld\n", ans);}int main(){    //std::ios::sync_with_stdio(false);    scanf("%lld%lld", &N, &W);    for(int i=1;i<=N;i++) scanf("%lld%lld", &w[i], &v[i]);    solve();    system("pause");}
0 0
原创粉丝点击