hdoj 3127 WHUgirls 【好题 DP】

来源:互联网 发布:小公司网络布线 编辑:程序博客网 时间:2024/04/29 12:47

WHUgirls

Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2286    Accepted Submission(s): 865


Problem Description
There are many pretty girls in Wuhan University, and as we know, every girl loves pretty clothes, so do they. One day some of them got a huge rectangular cloth and they want to cut it into small rectangular pieces to make scarves. But different girls like different style, and they voted each style a price wrote down on a list. They have a machine which can cut one cloth into exactly two smaller rectangular pieces horizontally or vertically, and ask you to use this machine to cut the original huge cloth into pieces appeared in the list. Girls wish to get the highest profit from the small pieces after cutting, so you need to find out a best cutting strategy. You are free to make as many scarves of a given style as you wish, or none if desired. Of course, the girls do not require you to use all the cloth.

Input
The first line of input consists of an integer T, indicating the number of test cases.
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.

Output
Output the maximum sum of prices that you can get on a single line for each case.

Constrains
0 < T <= 20
0 <= N <= 10; 0 < X, Y <= 1000
0 < xi <= X; 0 < yi <= Y; 0 <= ci <= 1000

Sample Input
12 4 42 2 23 3 9

Sample Output
9
 
 
大牛总结的很好,就借鉴一下。
 
原文出处:http://blog.csdn.net/u013480600/article/details/40512311
 

题意:

       现在有一块X*Y的矩形布条, 然后有n种规格的x[i]*y[i]的小布条, 每种布条可以卖出val[i]的价值. 问你原始的X*Y布条最多能卖多少价值?   其中每次切割布条只能水平或垂直的切, 且一刀到底.

分析:

       本题看起来比较麻烦, 但是搞懂原理后还是很简单的. 把当前还剩余的矩形布条看成容量, 那么我们就是再这有限的容量里面要找出最大价值的布条总和来.

       令dp[i][j]==x 表示当前长i和宽j的布条能切割出的最大价值为x.

这里有个结论要注意: 我们每次从大矩形中切割出一个小矩形, 总是沿着大矩形的顶角边缘切割将不会丢失最优解.

       比如一个i*j的大矩形, 我们如果要从中切割出一个x*y的小矩形, 有下面4种方式(大矩形可以选择先下垂直那刀先下水平那刀,小矩形能旋转):

(仔细体会上面这个图.)

       有了上面的图, 下面我们的递推公式就出来了:

       if(i>=r[k].x&& j>=r[k].y)

      dp[i][j]=max(dp[i][j] , max( dp[i-r[k].x][j]+dp[r[k].x][j-r[k].y] ,dp[i-r[k].x][r[k].y]+dp[i][j-r[k].y] )+r[k].val );

       if(i>=r[k].y && j>=r[k].x)

       dp[i][j]=max(dp[i][j] , max( dp[r[k].y][j-r[k].x]+dp[i-r[k].y][j] ,dp[i-r[k].y][r[k].x]+dp[i][j-r[k].x] )+r[k].val );

       上面两个公式好像看起来很复杂, 其实理解上面的图之后就很简单了.       本质就是:

       原始矩形能获得的最大价值 == max(小矩形价值 + 被水平一刀和竖直一刀切割后剩下的两个矩形能获得的最大价值和 )

       也就是求切割后的3个矩形的价值和, 看看哪种方式切割剩下的矩形价值和最大.(两刀之后,原始矩形必然变成3个新矩形)

       初始化: dp为全0.

       最终所求: dp[X][Y].

       注意:完全背包问题限制条件的维度j和物品编号的维度i的循环先后顺序是可以互换的. 但是此题必须先循环XY的维度,然后才是物品编号的维度. 因为一般的完全背包问题的最优解对于物品的选取顺序没有要求, 可以先区任何物品. 但是此题对于原始矩形来说, 你在它的顶角边缘先切割那个小矩形是明显不同的,有可能你先切割1号矩形就得不到最优解, 但是你先切割3号矩形才能得到最优解。

#include<stdio.h>#include<string.h>int max(int x,int y){    return x>y?x:y;}int dp[1010][1010];int x[15],y[15],value[15];int main(){    int t,n,X,Y;    int k,i,j;    scanf("%d",&t);    while(t--)    {        scanf("%d%d%d",&n,&X,&Y);        for(i=0;i<n;i++)        scanf("%d%d%d",&x[i],&y[i],&value[i]);        memset(dp,0,sizeof(dp));        for(i=0;i<=X;i++)        {            for(j=0;j<=Y;j++)            {                for(k=0;k<n;k++)                {                    if(i>=x[k]&&j>=y[k])                    dp[i][j]=max(dp[i][j],max(dp[i-x[k]][y[k]]+dp[i][j-y[k]],dp[i-x[k]][j]+dp[x[k]][j-y[k]])+value[k]);                    if(i>=y[k]&&j>=x[k])                    dp[i][j]=max(dp[i][j],max(dp[i-y[k]][x[k]]+dp[i][j-x[k]],dp[y[k]][j-x[k]]+dp[i-y[k]][j])+value[k]);                }            }        }        printf("%d\n",dp[X][Y]);    }    return 0;} 


 

 

 

 

0 0
原创粉丝点击