叠放箱子问题(方法二)【DP】

题目见:叠放箱子问题(方法一)【DP】


> 解题思路
这一道题比第一种方法更加优化。
f[i][j]表示前i个箱子排j个的最小总重量(这里的前i个箱子还是倒着来的,为从第i个箱子到第n个箱子),要求最小总重量是因为为了能让接下来的一个箱子有更多重量去装更多的箱子。

状态转移方程:

f[i][j]=min(f[i][j],f[i-1][j-1]+w[i])

输出的时候就是for语句(倒着)循环一下,如果循环到第一个f[1][i]的重量有存入过,就直接退出,输出i的值。

感性理解一下


> 代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,f[1005][1005]={0},w[1005],c[1005]={0};
//w数组存箱子自身重量,c数组存箱子承受重量
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&c[i]);
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=n;j++) f[i][j]=6000; //设标志(其实可以用inf,但是我不知道为什么我用inf会出错)
	f[n][0]=0; f[n][1]=w[n];
	for(int i=n-1;i>=1;i--)
	 for(int j=0;j<=n-i+1;j++) //j<=n-i+1为从i到n的箱子总个数
	 {
	    f[i][j]=f[i+1][j];
	 	if((f[i+1][j-1]<=c[i])&&(j!=0)) //如题描述,不能超过承受重量
	     f[i][j]=min(f[i][j],f[i+1][j-1]+w[i]);
	 }
	int ans;
	for(ans=n;ans>=0;ans--)
	 if(f[1][ans]!=6000) break;
	printf("%d",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43010386/article/details/84975815
今日推荐