2012年"浪潮杯"山东省第三届ACM大学生程序设计竞赛 Fruit Ninja I

题意:

水果忍者,给你n个水果的出现时间,出现位置,和他是否是好水果,切到好水果+1,切到坏水果-1,连续切到三次以上分数加倍。

每次只能切一刀,两刀之间的间隔大于等于m

问怎样安排能使得分最大;

解法:先求出每一秒出手能得到的最大的得分,双重暴力,

再用DP求出手时间;

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stdio.h>
using namespace std;

int s[10010][220],maxn[10010],vis1[10010],dp[10010],vis2[10010];
int main()
{
    int T,n,m,a,b,c;
    scanf("%d",&T);
    int t=1;
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(s,0,sizeof(s));
        memset(vis1,0,sizeof(vis1));
        memset(maxn,0,sizeof(maxn));
        memset(vis2,0,sizeof(vis2));
        for(int i=0; i<n; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(b==0)
            {
                s[a][c]=1;
            }
            else if(b==1)
            {
                s[a][c]=-1;
            }
            vis1[a]=1;
            if(c>vis2[a])//优化,算出最右边的位置
            {
                vis2[a]=c;
            }
        }
        for(int i=1; i<=10000; i++)//算出每一秒出手时能切到的最大分数
        {
            if(vis1[i]==1)
            {
                int max1=-1;
                for(int j=1; j<=vis2[i]; j++)
                {
                    int f=0;
                    int sum=0;
                    for(int k=j; k<=vis2[i]; k++)
                    {
                        if(s[i][k]==1)
                        {
                            f++;
                        }
                        else if(s[i][k]==-1)
                        {
                            if(f>=3)
                            {
                                sum+=f*2;
                                if(sum>max1)
                                {
                                    max1=sum;
                                }
                            }
                            else
                            {
                                sum+=f;
                                if(sum>max1)
                                {
                                    max1=sum;
                                }
                            }
                            f=0;
                            sum-=1;
                            if(sum>max1)
                            {
                                max1=sum;
                            }
                        }
                    }
                    if(f>0)
                    {
                        if(f>=3)
                        {
                            sum+=f*2;
                            if(sum>max1)
                            {
                                max1=sum;
                            }
                        }
                        else
                        {
                            sum+=f;
                            if(sum>max1)
                            {
                                max1=sum;
                            }
                        }
                    }
                }
                maxn[i]=max1;
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=10000; i++)//DP,决定哪一秒钟出手
        {
            if(i>m)
            {
                dp[i]=max(dp[i-1],dp[i-m-1]+maxn[i]);//如果出手,则和他i-m-1时候的状态有关系
            }
            else
            {
                dp[i]=max(dp[i-1],maxn[i]);
            }
        }
        printf("Case %d: ",t++);
        printf("%d\n",dp[10000]);
    }
    return 0;
}

 

posted @ 2016-04-30 22:53  萌萌哒哒哒  阅读(233)  评论(1编辑  收藏  举报