动态规划:叠放箱子
问题描述:
某港口有一批箱子,将其编号,分别为1至N。每个箱子的尺寸规格都是一样的,现在要将其中的某些箱子叠放起来,箱子叠放规则是:
1:每个箱子上最多只能直接叠放一个箱子;
2:编号较小的箱子不能直接放在编号较大的箱子之上;
3:每个箱子都给出了自身重量与可承受重量,每个箱子之上的所有箱子重量之和不得超过该箱的可承受重量.
要求:编程选择最多的满足条件的箱子。
分析:
当我看到条件的时候,自动与0-1背包问题对应:最多只能放一个就是选择放与不放的问题。
我们定义目标函数f[i][j]表示第i个箱子到第N个箱子中总重量为j的最大箱子数.
方程:
f[i[j]=max(f[i+1][j],f[i+1][j-weight[i]]+1);
能选的条件是:j>=weight[i]&&capacity[i]>=j-weight[i];
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=400;
int weight[maxn];
int dp[maxn][maxn];
int capacity[maxn];
bool mark[maxn];
int p[maxn];
int n,number;
bool visit[maxn];
void dfs(int cnt,int ans,int flag){//找出最优解
if(cnt==number){
if(ans==0){
for(int k=0;k<number;k++)
cout<<p[k]<<" ";
}
return ;
}
for(int i=flag;i<=n;i++){
if(visit[i]==false&&ans-weight[i]>=0){
visit[i]=true;
p[cnt]=i;
dfs(cnt+1,ans-weight[i],i);
visit[i]=false;
}
}
}
int main(){
int i,j;
cin>>n;
for(i=1;i<=n;i++){
cin>>weight[i];
}
for(i=1;i<=n;i++){
cin>>capacity[i];
}
int sum=0;
memset(dp,0,sizeof(dp));
memset(mark,false,sizeof(mark));
memset(visit,false,sizeof(visit));
for(i=n;i>=1;i--){
sum=0;
for(j=i;j<=n;j++)
sum+=weight[j];
for(int k=0;k<=sum;k++){
dp[i][k]=dp[i+1][k];//不选第i个箱子
if(k-weight[i]>=0&&capacity[i]>=k-weight[i]){//选择第i个箱子的条件k-weight[i]表示去除自身重量后
dp[i][k]=max(dp[i][k],dp[i+1][k-weight[i]]+1);
}
}
}
number=0;
for(i=1;i<=sum;i++)
number=max(dp[1][i],number);
for(i=1;i<=sum;i++)
if(dp[1][i]==number)
dfs(0,i,1);
return 0;
}