九度1453:Greedy Tino

来源:互联网 发布:淘宝号怎么看注册时间 编辑:程序博客网 时间:2024/05/17 17:43
题目1453:Greedy Tino

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:1448

解决:484

题目描述:

 Tino wrote a long long story. BUT! in Chinese...
So I have to tell you the problem directly and discard his long long story. That is tino want to carry some oranges with "Carrying pole", and he must make two side of the Carrying pole are the same weight. Each orange have its' weight. So greedy tino want to know the maximum weight he can carry.

输入:

The first line of input contains a number t, which means there are t cases of the test data.
for each test case, the first line contain a number n, indicate the number of oranges.
the second line contains n numbers, Wi, indicate the weight of each orange
n is between 1 and 100, inclusive. Wi is between 0 and 2000, inclusive. the sum of Wi is equal or less than 2000.

输出:

For each test case, output the maximum weight in one side of Carrying pole. If you can't carry any orange, output -1. Output format is shown in Sample Output.

样例输入:
151 2 3 4 5
样例输出:
Case 1: 7

*************************************************

这道题属于dp中的难题,不过还是跟着写了一遍,关键还是体会那种递推的思想。所谓动态规划,我理解的是,问题的解决不是一下子就奔着最终结果去,而是从小缩小问题的规模,从零开始,一点一点递推向最终的结果,其中可能还含有模拟类问题的思想。如本题,就是模拟了往天平上放橘子的过程:放第一个,放第二个……一直放完第n个为止。在这个过程中,分别判断使第一堆与第二堆的重量差增大list[i]/减小list[i]/不变,这三种情况中哪种会使两堆的重量和最大(这听起来有点荒诞,因为若使两堆重量和最大的话那一定是要往堆中加柑橘啊,怎么还会有第三种不变的情况呢?注意到dp[i][j]表示的是处理完第i个后,当第一堆比第二堆重j时,两堆的最大重量和,有了这个限制,就知道傻乎乎的一味的往里放是不对的了。。)可见,考虑问题要十分客观。

****************************************************

#include <cstdio>#define OFFSET 2000#define INF 0x7fffffffusing namespace std;int dp[101][4001];      //重量差可正可负,而且注意,这里数组下标是有实际意义的,如dp[i][4000]                        //就代表第一堆比第二堆重2000的情况,因此必须4001列,而不能是4000列。int list[101];int main(){    int T;    int cas=0;    scanf("%d",&T);    while(T--){        int n;        scanf("%d",&n);        int cnt=0;        bool Havezero=false;                    for(int i=1;i<=n;i++){            scanf("%d",&list[++cnt]);            if(list[cnt]==0){                cnt--;                Havezero=true;            }                   //去除重量为0的柑橘        }        n=cnt;        int i,j;        for(i=-2000;i<=2000;i++){            dp[0][i+OFFSET]=-INF;        }        dp[0][0+OFFSET]=0;        for(i=1;i<=n;i++){              //遍历每个柑橘            for(j=-2000;j<=2000;j++){   //遍历每种重量差。但是重量差受到下面if的条件限制                int tmp1=-INF,tmp2=-INF;                if(j+list[i]<=2000&&dp[i-1][j+list[i]+OFFSET]!=-INF){                    tmp1=dp[i-1][j+list[i]+OFFSET]+list[i];         //情况1:把第i个柑橘放在第二堆中                }                if(j-list[i]>=-2000&&dp[i-1][j-list[i]+OFFSET]!=-INF){                    tmp2=dp[i-1][j-list[i]+OFFSET]+list[i];         //情况2:把第i个柑橘放在第一堆中                }                if(tmp1<tmp2)                    tmp1=tmp2;                if(tmp1<dp[i-1][j+OFFSET])                    tmp1=dp[i-1][j+OFFSET];                         //情况3:第i个柑橘不放在任何一堆中                    //保证tmp1中存的是最大重量的情况                dp[i][j+OFFSET]=tmp1;            }        }        printf("Case %d: ",++cas);        if(dp[n][0+OFFSET]==0){            puts(Havezero==true?"0":"-1");        }        else            printf("%d\n",dp[n][0+OFFSET]/2);               //最后处理柑橘重量为0的情况    }    return 0;}

******************************

坚持,而不是打鸡血~

原创粉丝点击