问题是:
杰瑞在有趣的游戏中失去了自己:水果忍者。 Fruit Ninja是一款iPhone和iPad游戏,玩家可以从屏幕底部切割水果,并通过一片切割两个以上的水果获得奖励。一旦水果被切割,它就会变成小块,不能再切割了。经过数月的训练,他成为这场比赛的职业球员。实际上,他可以随时切断屏幕上的所有水果。杰里也有一个坏习惯,他不愿意为未来的切割留下一些成果。换句话说,在杰瑞削减水果之后,屏幕上的所有水果都会破裂,没有人离开。这就是为什么他所有的朋友都称他为Juice Extractor。
现在他只考虑奖金,当他削减两个以上的成果时,他可以获得一些奖励分数,与他当时切片的果实数量相同。例如,如果Jerry用一个切片切割4个水果,他可以从这个切片中获得4个分数。
杰瑞得到水果时间表后,他知道每一个水果的出现时间和消失的时间。他只能在出现的时间和消失的时间之间将水果切成碎片。他想知道他可以获得的最高奖励分数。
输入
有几个测试用例;输入的第一行包含一个整数T,表示测试用例的数量。 (T <= 200)
对于每个测试用例,第一行包含一个整数N,表示水果的总数。 (1 <= N <= 1000)
接下来的N行,每行描述一个水果。对于每一行,有两个整数Xi和Yi,其中Xi是果实的出现时间,Yi是该果实消失的时间。 (0 <= Xi <= Yi <= 1000000000)
输出
对于每个测试用例,输出一个整数,表示Jerry可能获得的最大分数。有关详细信息,请参阅示例。
实施例
输入: 1 10 1 10 2 11 3 12 4 13 13 14 14 15 13 19 20 22 21 23 22 24
输出: 案例#1:10
这是代码: 它根据开始时间对时间间隔进行排序.dp [i]说明了第i个水果出现的时间。我们将仅在出现水果时进行切割,因为它将涵盖所有情况
#include<iostream>
#include<vector>
#include<algorithm>
#include<memory.h>
using namespace std;
struct node
{
int x,y;
};
int cmp(node a,node b)
{
if(a.x!=b.x)
return a.x<b.x;
return a.y<b.y;
}
int main()
{
int test;
cin>>test;
int t=0;
int dp[1002];
while(test--)
{
t++;
int n;
cin>>n;
vector<node> v(n);
for(int i=0;i<n;i++)
{
int a,b;
cin>>a>>b;
v[i].x=a;
v[i].y=b;
}
sort(v.begin(),v.end(),cmp);
memset(dp,0,sizeof(dp));
int mx=0;
for(int i=0;i<n;i++)
{
int id=100000,match=0;
for(int j=0;j<=i;j++)
{
if(v[j].y>=v[i].x)
{
id=min(id,j);
match++;
}
}
for(int j=id;j<=i;j++)
{
if(match>2)
dp[i+1]=max(dp[i+1],dp[j]+match);
else
dp[i+1]=max(dp[i+1],dp[j]);
if(v[j].y>=v[i].x)
match--;
}
dp[i+1]=max(dp[i+1],dp[i]);
mx=max(mx,dp[i+1]);
}
cout<<"Case #"<<t<<": "<<mx<<"\n";
}
return 0;
}
答案 0 :(得分:0)
当具有相同的开始时间时,可能会出错。
我使用您的代码运行此测试用例:
10
1 1
1 2
3 3
1 4
3 5
3 6
3 7
8 8
3 9
3 10
您的代码输出 10 但答案实际上是 9
由于这个测试用例,我有几个WA, 我处理完这个案子后得到了AC ......我将分享我的经验,请看看你是否也有同样的错误。
使用此测试用例,我的代码将输出 10,我将快速解释如下:
让dp(i)成为您在第i个片段的开始时间最后一次剪辑的状态
显然,对于所有j <1,dp(i)=最大(dp(j)+段的数量(在j之后)与第i个段相交)。我
从物理角度来说,这意味着你在第j段的开始时间有第二次最后一次切割这是逻辑除了,如果第j段和第i段的开始时间是一样的!然后它不是2个不同的切割但是相同的切割!
要处理此问题,正确的方法是选择仅具有相同开始时间的连续段的最后一段!
(假设片段已经按开始时间排序,下面的顺序是排序顺序)
这是错误,我的程序(也许你的程序)给出输出10因为(使用0为基础)
DP(9)= DP(6)+ [7,9]
中的#重叠段= 7 + 3 = 10!
如果你看得更深,DP(6)= 7实际上是正确的,因为它之后不会考虑这些段。但是你不应该使用DP(6)更新任何DP(X)的X> 6!,因为具有相同开始时间(第6段)的最后一段是8-细分
简而言之,如果我们使用某个DP状态而不是最后一个具有相同启动时间的DP状态来更新其他DP状态,则可能会出现问题。
我的解决方案是,当我在第i个段上执行DP时,每当我发现一些段j具有与段i(j 我将DP(j)设置为负无穷大,因此它不能足以更新其他状态。
已编辑:已接受的已添加代码 根据OP的要求,下面是我的代码
#include<bits/stdc++.h>
#define pii pair<int,int>
#define x first
#define y second
#define INF 1LL<<28
using namespace std;
int T,n;
int dp[1005];
pii a[1005];
int main(){
scanf("%d", &T);
for(int qwe=1; qwe <= T; qwe++){
scanf("%d", &n);
for(int i=0; i<n;i++) scanf("%d%d", &a[i].x, &a[i].y);
sort(a, a+n);
memset(dp,0,sizeof(dp));
for(int i=0; i<n;i++){
int cnt = 0;
for(int j=i-1; j>=0; j--){
if(a[j].x == a[i].x){dp[j] = -INF; cnt++; continue;}
cnt += (a[i].x >= a[j+1].x && a[i].x <= a[j+1].y);
dp[i] = max(dp[i], dp[j] + (cnt>2? cnt:0));
}
cnt += (a[i].x >= a[0].x && a[i].x <= a[0].y);
dp[i] = max(dp[i], (cnt>2? cnt:0));
}
printf("Case #%d: %d\n", qwe, dp[n-1]);
}
return 0;
}