UVa12018 Juice Extractor ( DP )

原题链接:UVa12018
原题如下:

Jerry loses himself in the interesting game: Fruit Ninja. Fruit Ninja is a game of iPhone and iPad in which the players cut the fruits coming from the bottom of the screen and gain the bonus from cutting more than two fruits with a single slice. Once a fruit is cut, it breaks into small pieces and cannot be cut any more. After months of training, he becomes pro of this game. Actually, he can cut all the fruits on the screen at any time. Jerry also has a bad habit that he has no willing to leave some fruits for the future cutting. In the other words, after Jerry cuts the fruits, all the fruits on the screen breaks and no one left. That is why all his friends call him ‘Juice Extractor’. Now he only consider about the bonus, when he cuts more than two fruits, he can gain some bonus scores as same as the number of fruits he slice at that time. For example, if Jerry cuts 4 fruits with a single slice, he can get 4 scores from this slice. After Jerry gets the fruit schedule, he knows the appearing time and the disappearing time for every single fruit. He can only cut a fruit into pieces between its appearing time and disappearing time inclusive. He wants to know the maximum possible bonus scores he can receive.
Input
There are several test cases; the first line of the input contains a single integer T, denoting the number of the test cases. (T ≤ 300) For each test case, the first line contains an integer N, denoting the total number of fruits. (1 ≤N ≤ 1000) The next N lines, each line describe a fruit. For each line, there are two integers Xi and Yi, where Xi is the appearing time of the fruit and Yi is the disappearing time of this fruit. (0 ≤ Xi ≤ Yi ≤ 1000000000)
Output
For each test case, output a single integer denoting the maximum scores that Jerry could possibly gain. See the sample for further details.
Sample Input
1
10
1 10
2 11
3 12
4 13
13 14
14 15
13 19
20 22
21 23
22 24
Sample Output
Case #1: 10

题意:

类似于水果忍者游戏,给你多个水果(n<=1000)的出现时间和消失时间( 1<=Xi<=Ti<=1e9 ),当同时切碎三个及以上的水果时,获得切碎水果数量的分数,切碎三个数量以下的水果不算分数。注意:你如果在某一刻要切碎某一个在那一刻已经出现的水果,只能在同时把所有的已经出现的水果切碎。

让你求出可以获得的最大分数。

分析:

对于一道题目,我们通常会根据题目的数量级判断算法。
此题的n最大为1000,样例数量为300,时间为3000ms,最差的时间复杂度的算法可以为 O(n*n)。在这个时间复杂度下,并且通过题目描述,我们可以知道,这道题不适合暴力求解,所以考虑动态规划的解法。

状态:

dp[i]: 从开始到当第i个水果出现时,能获得的最大分数。

状态转移方程:

dp[i]=max{ dp[j-1]+Vji} , 1<=j<=i 。
注意:
1.这里的Vji表示从第j个水果到第I个水果(包括两个端点),有多少个水果的消失时间大于等于第i个水果的出现时间。
2.水果出现的时间需要先进行排序。先按出现时间升序排列,再按消失时间升序排列(其实消失时间是无所谓的)。这样和第一点联合起来就能保证:在第i个水果前面的水果如果消失时间大于等于水果i的出现时间,这两个就能一起切碎。

AC代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct Fruit{
    int st,ed;
}fru[1000+10];
bool cmp(struct Fruit f1,struct Fruit f2)
{
    if(f1.st==f2.st){
        return f1.ed<f2.ed;
    }
    return f1.st<f2.st;
}
int dp[1000+10];
int main(void)
{
    int t,caz;
    scanf("%d",&t);
    caz=0;
    while(t--){
        memset(dp,0,sizeof(dp));
        printf("Case #%d: ",++caz);
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&fru[i].st,&fru[i].ed);
        }
        sort(fru+1,fru+n+1,cmp);
        int ans=0;
        for(int i=3;i<=n;i++){
            int temp=0;
            if(i+1<=n&&fru[i].st==fru[i+1].st) continue;//!!!!
            for(int j=i;j>0;--j){
                if(fru[j].ed>=fru[i].st){
                    ++temp;
                }
                dp[i]=max(dp[i],dp[j-1]+(temp>=3?temp:0));
                ans=max(ans,dp[i]);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

注意感叹号的地方,因为是一刀切光,如果没有标注感叹号那一句,这组样例过不了:
1
6
1 4
2 5
3 6
3 9
7 11
8 10

猜你喜欢

转载自blog.csdn.net/gymgym1212/article/details/78171681
今日推荐