题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3127
WHUgirls
Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1111 Accepted Submission(s): 451
The first line of each case consists of three integers N, X, Y, N indicating there are N kinds of rectangular that you can cut in and made to scarves; X, Y indicating the dimension of the original cloth. The next N lines, each line consists of two integers, xi, yi, ci, indicating the dimension and the price of the ith rectangular piece cloth you can cut in.
Constrains
0 < T <= 20
0 <= N <= 10; 0 < X, Y <= 1000
0 < xi <= X; 0 < yi <= Y; 0 <= ci <= 1000
1 2 4 4 2 2 2 3 3 9
9
题目的意思是有一块大布,你要在上面裁剪小块布料,每一种布料都有相应的权重。而且在大布上裁剪相同的多次(完全背包)。要你给出在有限大布内裁剪之后的最大权重。反过来想,这一整块布就像一个二维的背包,而小布就是物品。我们要尽量的往里面装东西,使得里面装下的物品的权重之和最大。而且每种物品都是可以重复使用的,那么这就转换成了一个背包问题。但是怎样装呢?我们就从左下往右上方装。经孟成博同学点拨,主有如下两种方案。
如图就是所说的两种方案。红色的就是要装的小布块。而且还要注意的小布块是可以横着放,即x,y值交换位置。我们以f[m][n]来表示以m,n为长宽的布料所能取得的最大权重。则
if(m>=r[i].x && n>=r[i].y) //正着放
dp[m][n] = max3(dp[m-r[i].x][n] + dp[r[i].x][n-r[i].y]+ r[i].pro,dp[m][n-r[i].y] + dp[m-r[i].x][r[i].y]+r[i].pro,dp[m][n]);
if(m>=r[i].y && n>=r[i].x) //倒着放
dp[m][n] = max3(dp[m-r[i].y][n] + dp[r[i].y][n-r[i].x]+ r[i].pro,dp[m][n-r[i].x] + dp[m-r[i].y][r[i].x]+r[i].pro,dp[m][n]);
在后面的代码中你还会发现,小布块的种数循环放在里面去了。为什么呢?经薛智文同学的点拨,我们是这样理解的。因为二维的不像一维的,即使你要放下也是要有讲究的,如果你随意乱放的话有可能就装不下最大的,这个大家应该有生活体验。所以如果放在外面,一个一个装的话就失去了调整的机会。但是如果把物品种数放在里面的话,你就有一个调整的过程,这样就可以找到最合适的方法从而使得你放下的是最大权重的方法。在此感谢孟成博和薛智文同学的点拨,让我更好的理解了这个题目,对二维完全背包的解法也有了更深的体会。下面上代码。
#include<iostream>
using namespace std;
#define MAX 1002
struct rect
{
int x,y;
int pro;
}r[12];
int dp[MAX][MAX];
int max3(int a,int b,int c)
{
int temp = a>b?a:b;
return temp>c?temp:c;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int num,x,y;
scanf("%d%d%d",&num,&x,&y);
for(int i=1;i<=num;i++)
cin>>r[i].x>>r[i].y>>r[i].pro;
memset(dp,0,sizeof(dp));
int m,n;
//是完全背包啊,伤不起啊
for(m=0;m<=x;m++)
{
for(n=0;n<=y;n++)
{
for(int i=1;i<=num;i++)
{
if(m>=r[i].x && n>=r[i].y) //正着放
dp[m][n] = max3(dp[m-r[i].x][n] + dp[r[i].x][n-r[i].y]+ r[i].pro,dp[m][n-r[i].y] + dp[m-r[i].x][r[i].y]+r[i].pro,dp[m][n]);
if(m>=r[i].y && n>=r[i].x) //倒着放
dp[m][n] = max3(dp[m-r[i].y][n] + dp[r[i].y][n-r[i].x]+ r[i].pro,dp[m][n-r[i].x] + dp[m-r[i].y][r[i].x]+r[i].pro,dp[m][n]);
}
}
}
printf("%d\n",dp[x][y]);
}
system("pause");
return 0;
}