Hangzhou Electric ACM-2546, meal card (DP)

Posted by FezEvils on Sat, 16 Nov 2019 16:29:22 +0100

One dimensional knapsack problem.
Breakthrough: rank the prices of dishes from small to large, DP the first n-1 items, and find out the largest sum of consumption in the scheme where the consumption amount does not exceed m-5. On this basis, m - (sum+price[n]) is the minimum balance in the card.
Therefore, we DP should find the optimal solution within the balance of 0~m-5.
Status: dp[i,j] is the maximum consumption that can be made in the first i vegetables when the balance is j.
State transfer equation:
dp[i,j]=
If (J < price [i]) DP [I, J] = DP [I-1, J]; (not optional)
else dp[i,j]=max(dp[i-1,j],dp[i-1,j-p[i]]+p[i]); (optional, try it with or without)
Boundary treatment: dp[0,0~m]=0.
The optimal solution is dp[n-1,m-5].

The code is as follows:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e3+5;
int dp[maxn][maxn],p[maxn];		//You can use the scrolling array to reduce the space complexity. See another code later
int main()
{
	int n,m,i,j;
	while(~scanf("%d",&n)&&n)
	{
		for(i=1;i<=n;i++)
			scanf("%d",&p[i]);
		sort(p+1,p+1+n);
		scanf("%d",&m);
		for(i=0;i<=m-5;i++)
			dp[0][i]=0;
		if(m<5)	printf("%d\n",m);	//M < 5 can't buy anything
		else
		{
			for(i=1;i<=n-1;i++)
				for(j=0;j<=m-5;j++)		//The range of j is 0~m-5
					if(j<p[i])
						dp[i][j]=dp[i-1][j];
					else dp[i][j]=max(dp[i-1][j],dp[i-1][j-p[i]]+p[i]);
			printf("%d\n",m-dp[n-1][m-5]-p[n]); 
		 } 
	}
	return 0;
 } 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e3+5;
int dp[maxn],p[maxn];
int main()
{
	int n,m,i,j;
	while(~scanf("%d",&n)&&n)
	{
		for(i=1;i<=n;i++)
			scanf("%d",&p[i]);
		sort(p+1,p+1+n);
		scanf("%d",&m);
		for(i=0;i<=m-5;i++)
			dp[i]=0;
		if(m<5)	printf("%d\n",m);
		else
		{
			for(i=1;i<=n-1;i++)
				for(j=m-5;j>=p[i];j--)
					dp[j]=max(dp[j],dp[j-p[i]]+p[i]);
			printf("%d\n",m-dp[m-5]-p[n]); 
		 } 
	}
	return 0;
 }