SDUT:2412 Fruit Ninja I(动态规划)

题意:一个切水果游戏。每秒出现一些水果,它们都在一条线上,有好水果和坏水果,好的可以加分,坏的减分,每次连续切好水果三个以上可以分数加倍。每秒只能切一次,每切一次要间隔m秒。问最多得多少分。

思路:对于每一秒的时候,可以确定连续的好水果一定会一起切,可以合并。然后用最大连续数组和求解该秒可得最优解。然后再所有的时间内进行简单动规就行了。

#include <bits/stdc++.h>  
using namespace std;  
struct Fruit  
{  
    int t,good,p,vis,val;  
    Fruit(int a=0,int b=0,int c=0,int d=1,int e=1):t(a),good(b),p(c),vis(d),val(e)  
    {  
        if(b==0) val=1;  
        else val=-1;  
    }  
    bool operator < (const Fruit &rhs) const  
    {  
        return p<rhs.p;  
    }  
};  
const int maxn=10005;  
vector<Fruit> vec[maxn];  
void init(int n)  
{  
    for(int i=1; i<=n; ++i)  
        vec[i].clear();  
}  
int val[maxn];  
int dp[maxn];  
int bestS(const vector<Fruit> &v)  
{  
    int ans=0;  
    int sum=0;  
    for(int i=0; i<v.size(); ++i)  
    {  
        if(sum<0) sum=v[i].val;  
        else sum+=v[i].val;  
        ans=max(ans,sum);  
    }  
    return ans;  
}  
int main()  
{  
    int T,kase=0;  
    scanf("%d",&T);  
    while(T--)  
    {  
        int n,m;  
        scanf("%d%d",&n,&m);  
        int maxt=0;  
        for(int i=1; i<=n; ++i)  
        {  
            int a,b,c;  
            scanf("%d%d%d",&a,&b,&c);  
            vec[a].push_back(Fruit(a,b,c));  
            maxt=max(maxt,a);  
        }  
        for(int i=1; i<=maxt; ++i)  
            sort(vec[i].begin(),vec[i].end());  
        for(int i=1; i<=maxt; ++i)  
        {  
            vector<Fruit> v;  
            for(int j=0; j<vec[i].size(); ++j)  
            {  
                if(v.empty()) v.push_back(vec[i][j]);  
                else  
                {  
                    int sz=v.size()-1;  
                    if(v[sz].good==0&&vec[i][j].good==0)  
                    {  
                        v[sz].vis++;  
                        if(v[sz].vis==2) v[sz].val++;  
                        else if(v[sz].vis==3) v[sz].val=v[sz].val*2+2;  
                        else v[sz].val+=2;  
                    }  
                    else  
                        v.push_back(vec[i][j]);  
                }  
            }  
            val[i]=bestS(v);  
        }  
        for(int i=1; i<=maxt; ++i)  
        {  
            int last=0;  
            if(i-m-1>=1) last=dp[i-m-1];  
            dp[i]=max(dp[i-1],val[i]+last);  
        }  
        printf("Case %d: %d\n",++kase,dp[maxt]);  
        init(maxt);  
    }  
    return 0;  
}  
   


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值