HDU1171(背包)
题意:求把总价值分为两个数,使这两个数接近相等,而且这两个数必须由所有设备中的其中几种设备价值构成,并先输出比较大的数,再输出另一个数。
解题思路:DP算法,背包问题,求法是先求出总价值sum,再用dp[]求sum/2最多能放多少价值!即可以求出其中一个数了,另一个就是sum-dp[sum/2]了……
状态:f[j]:表示软件学院取得容量为j时能获得的最大值,j<=sum/2; 状态转移:f[j]=max{f[j], f[j-v[i]]+v[i]}
注意数组的大小(0<n<=50,0<v<=50,0<m<=100)
View Code
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 using namespace std;
5 #define MAX 300000
6 int dp[MAX],v[1000],m[1000];
7 int main()
8 {
9 int i,j,n,k;
10 while(cin>>n&&n>=0)
11 {
12 int sum=0;
13 for(i=0;i<n;i++)
14 {
15 cin>>v[i]>>m[i];
16 sum+=v[i]*m[i];
17 }
18 memset(dp,0,sizeof(dp));
19 for(i=0;i<n;i++)
20 for(j=1;j<=m[i];j++)
21 for(k=sum/2;k>=v[i]*j;k--)
22 if(dp[k]<dp[k-v[i]]+v[i])
23 dp[k]=dp[k-v[i]]+v[i];
24 if(sum-dp[sum/2]>dp[sum/2])
25 cout<<sum-dp[sum/2]<<" "<<dp[sum/2]<<endl;
26 else cout<<dp[sum/2]<<" "<<sum-dp[sum/2]<<endl;
27 }
28 return 0;
29 }
2 #include <cstdio>
3 #include <cstring>
4 using namespace std;
5 #define MAX 300000
6 int dp[MAX],v[1000],m[1000];
7 int main()
8 {
9 int i,j,n,k;
10 while(cin>>n&&n>=0)
11 {
12 int sum=0;
13 for(i=0;i<n;i++)
14 {
15 cin>>v[i]>>m[i];
16 sum+=v[i]*m[i];
17 }
18 memset(dp,0,sizeof(dp));
19 for(i=0;i<n;i++)
20 for(j=1;j<=m[i];j++)
21 for(k=sum/2;k>=v[i]*j;k--)
22 if(dp[k]<dp[k-v[i]]+v[i])
23 dp[k]=dp[k-v[i]]+v[i];
24 if(sum-dp[sum/2]>dp[sum/2])
25 cout<<sum-dp[sum/2]<<" "<<dp[sum/2]<<endl;
26 else cout<<dp[sum/2]<<" "<<sum-dp[sum/2]<<endl;
27 }
28 return 0;
29 }