HDU1171 Big Event in HDU

水题?

题目链接

思路

  • 这道题目看似与dp无关,其实换个思路就是一个01背包。
  • 这道题可以用0-1背包。将所有设施的价值全部加起来,然后分成2组,要使这2组设施的价值尽可能等,即要求它们2组的价值差要最小。那么我们可以首先将求价值总和的一半儿,然后先算其中一组的价值,此时价值总和的一半就相当于背包的最大容量,然后求不超过背包最大容量的情况下背包所能得到的最大价值,总价值-最大价值就是另一组设施的价值。要注意的是,这里每件物品的重量就是每件物品的价值。还要 记住,每次的背包的N和V都要更新。

我的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<string>
#include<cmath>
#include<sstream>
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const int eps=1e-10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;//int2147483647//ll9e18//unsigned ll 1e19
const int maxn=100005;
int m[maxn],v[maxn],dp[maxn];

int a[maxn];
int main()
{
int n,sum_v,sum_m;//v,m
while(~scanf("%d",&n) && n >= 0)
{
sum_v = 0,sum_m = 0;
int z = 0;
for(int i = 0;i < n;i++)
{
scanf("%d%d",&v[i],&m[i]);
sum_v += v[i] * m[i];
sum_m += m[i];
for(int j = 0;j < m[i];j++)
{
a[z] = v[i];
z++;
}
}
memset(dp,0,sizeof(dp));
for(int i = 0;i < sum_m;i++)
{
for(int j = sum_v / 2;j >= a[i];j--)
{
dp[j] = max(dp[j],dp[j - a[i]] + a[i]);
}
}
printf("%d %d\n",max(dp[sum_v / 2],sum_v - dp[sum_v / 2]),min(dp[sum_v / 2],sum_v - dp[sum_v / 2]));
}
return 0;
}

大佬代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int V,N,weight[10002],v[10002];
long int f[100002];
int OnePack() //0-1背包的主要思想
{
memset(f,0,sizeof(f));
for(int i=0;i<N;i++)
{
for(int j=V;j>=weight[i];j--)
f[j]=max(f[j],f[j-weight[i]]+v[i]);
}
return f[V];
}
int main()
{
int t,a,b,x,y,z;
while(scanf("%d",&t)&&t>0)
{
N=V=0; //每次背包的N和V都要更新
int i=0;
while(t--)
{
scanf("%d%d",&a,&b);
N+=b;
V+=a*b;
while(b--)
{
v[i]=a; //记录每件物品的价值
weight[i]=a; //记录每件物品的重量
i++;
}
}
z=V;
V/=2;
x=max(OnePack(),z-OnePack()); //最大的设施价值放前面
y=min(OnePack(),z-OnePack());
cout<<x<<" "<<y<<endl;
}
return 0;
}

参考博客