题意:
水果忍者游戏,给出N个水果的出现时间和消失时间。
每次切可以清除该时刻中屏幕上的所有水果,只有combo>=3的时候才得分,得分为combo的值。
题解:
可以把每个水果看成是一段时间区间。
然后把这些区间按照出现时间为第一关键字,消失时间为第二关键字排序。
我们定义dp方程dp[i]表示最后一刀切掉第i个水果,所获得的最大积分。
那么,最优的方案肯定是在第i个水果出现时间进行切。
这样的话,转移方程
dp[i] = max(dp[i],dp[j-1]+sum);
其中sum表示j到i之间所有结束时间>=第i个水果出现时间的水果数量。
但是注意!
这个题目有一个限制,就是说每次切必定将所有的水果都切完。
也就时候如果j-1水果的出现时间=第j个水果的出现时间的话,那么是不能进行转移的,因为切第j-1个水果的时候必然把第j个水果切掉,不会留下。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
bool cmp(P p1,P p2){if(p1.first == p2.first) return p1.second < p2.second;return p1.first < p2.first;
}
const int maxn = 1005;
P ps[maxn];
int dp[maxn];
int n;
int main(){int T,cas=0;cin>>T;ps[0].first = ps[0].second = -1;while(T--){memset(dp,0,sizeof(dp));scanf("%d",&n);for(int i = 1;i <= n;++i){int a,b;scanf("%d %d",&a,&b);ps[i] = make_pair(a,b);} sort(ps+1,ps+1+n,cmp);int ans = 0;if(n >= 3){for(int i = 3;i <= n;++i){int tim = ps[i].first;int sm = 0;for(int j = i;j >= 1;--j){if(ps[j].second >= tim) sm++;if(ps[j-1].first != ps[j].first)dp[i] = max(dp[i],dp[j-1] + (sm >= 3?sm:0));}ans = max(ans,dp[i]);}}printf("Case #%d: %d\n",++cas,ans);}return 0;
}