hdu1171+1203+2546
这三题都是常规的dp,可以转化为经典的01背包问题,要注意的是为了防止内存超限,不能使用二维的dp数组,要用一维的。
1171
题目可以简单的描述为将组不同大小的数分成两堆,使两堆数的总和尽可能的接近,要注意每组数据之前要进行初始化,否则会WA
step1:要将数据按照个数和大小统一存到一个一维数组中,统计总和sum
step2:假设“背包”的容量为sum/2,进行01背包dp过程
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<mem.h>
#include<math.h>
using namespace std;
int dp[2500005],a[5005];
int main()
{
int n,sumv,i,j,v,m,cnt;
while(~scanf("%d",&n)&&n>0)
{
if(n==-1) break;
sumv=0;
cnt=1;
memset(a,0,sizeof(a));
for(i=1;i<=n;i++)
{
scanf("%d%d",&v,&m);
sumv+=v*m;
for(j=1;j<=m;j++)
{
a[cnt] = v;
cnt++;
}
}
int t = sumv/2;
memset(dp,0,sizeof(dp));
for(i=1;i<cnt;i++)
{
for(j=t;j>=a[i];j--)
{
dp[j] = max(dp[j],dp[j-a[i]]+a[i]);
}
}
int ans=max(dp[t],sumv-dp[t]);
printf("%d %d\n",ans,sumv-ans);
}
return 0;
}
1203
本题中,“背包”的容量是拥有的学费数,由于要求的是得到至少一份offer的最大概率,我们在dp的过程中,最方便的是记录一份offer都不得到的概率,并且要把原始01背包的max改为min。要注意这里的dp数组要初始化为1,最后的答案要用1来减去dp[n]。
下面展示一些 内联代码片
。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<mem.h>
#include<math.h>
using namespace std;
int a[10005],n,m,i,j;
double dp[10005],b[10005];
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break;
for(i=1;i<=m;i++)
{
scanf("%d%lf",&a[i],&b[i]);
}
for(i=0;i<=n;i++) dp[i] = 1;
for(i=1;i<=m;i++)
{
for(j=n;j>=a[i];j--)
{
dp[j] = min(dp[j],dp[j-a[i]]*(1-b[i]));
}
}
printf("%.1lf%%\n",100-dp[n]*100);
}
return 0;
}
2546
根据题意,特殊处理初始余额小于5的情况。
当初始余额大于等于5时,我们的“背包”容量是:初始余额m-5
根据题意,dp的过程不需要对菜品价格最贵的菜品进行,因此我们提前对菜品进行价格从低到高排序。
最后的答案要减去最贵的菜品价格。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<mem.h>
#include<math.h>
using namespace std;
int dp[1005][1005],n,m,i,j,maxi,a[1005],maxa=-1;
int main()
{
while(~scanf("%d",&n))
{
maxi = 0;
maxa = -1;
if(n==0) break;
for(i=0;i<n;i++)
{
scanf("%d",&a[i+1]);
if(a[i+1] > maxa)
{
maxa = a[i+1];
maxi = i+1;
}
}
scanf("%d",&m);
if(m<=4)
{
printf("%d\n",m);
continue;
}
for(i=0;i<=m-5;i++) dp[0][i] = 0;
sort(a+1,a+n+1);
for(i=1;i<n;i++)
{
for(j=0;j<=m-5;j++)
{
if(a[i]<=j)
{
dp[i][j] = max(dp[i-1][j],dp[i-1][j-a[i]]+a[i]);
}
else
{
dp[i][j] = dp[i-1][j];
}
}
}
int s=-1;
for(i=0;i<=m-5;i++)
{
s = max(dp[n-1][i],s);
}
printf("%d\n",m-s-a[n]);
}
return 0;
}
科研和做项目之余,刷一些简单题更新一下大脑。
2020/11/16