题目大意:有n只怪兽排成一列,体重大的可以吃掉相邻体重比他小的,吃掉后,体重便会相应地增加。给定初始怪兽和目标状态怪兽体重,问是否可能达成目标状态。可能输出“”YES“和步骤,不可能输出“NO”。
因为只能吃相邻的,所以目标状态肯定是由初始状态的连续子段和组成。那么遍历目标状态的各体重,判断能否由初始状态到达,即检查是否初始状态有连续子段的和等于该体重。若有连续子段等于该目标体重,那么是否一定能达到呢?可以发现,只要连续子段中各体重不全相等或者连续子段长度等于1,那么一定通过“一直向左吃之后一直向右吃”或者“一直向右吃之后一直向左吃”达到。
至于步骤的输出,遍历检查时记下各目标体重对应的连续子段的左右端点,在通过以上方法“吃”即可。
那么“吃“的起始点该怎么找呢?率先开吃的怪兽应该满足以下条件:1)它的体重是最重的,2)它的两边至少存在一个比它轻的。这两个条件保证了它这一次有的吃,而且吃完后还是最重的。
另外“NO”的判断,要注意吃完还有多余的怪兽,以及怪兽不够吃均是“NO”。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=500+15;
int sum[maxn];
int n, m, a[maxn], b[maxn];
int l[maxn], r[maxn];
bool can(int s,int t){
int val=a[s];
for(int i=s;i<=t;i++)
if(a[i]!=val)
return true;
if(t==s) return true;
return false;
}
void make(int cnt,int l,int r){
int pos=l;
for(int i=l;i<=r;i++)
if(a[i]>a[pos])
pos=i;
else if(a[i]==a[pos]){
if(pos==l)
pos=i;
else if(a[pos-1]==a[pos]&&a[pos]==a[pos])
pos=i;
}
// printf("pos=%d\n",pos);
if(pos==l||a[pos]==a[pos-1]){
for(int i=pos;i<r;i++)
printf("%d R\n",cnt+pos-l+1);
for(int i=pos;i>l;i--)
printf("%d L\n",cnt+i-l+1);
}else{
for(int i=pos;i>l;i--)
printf("%d L\n",cnt+i-l+1);
for(int i=pos;i<r;i++)
printf("%d R\n",cnt+1);
}
}
int main(){
int no_ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d",&b[i]);
int i=1, j;
for(j=1;j<=m;j++){
int t=i;
while(t<=n&&sum[t]-sum[i-1]<b[j])
t++;
if(t>n||sum[t]-sum[i-1]!=b[j]||!can(i,t)){
no_ans=1;
break;
}
if(j==m&&t!=n){
no_ans=1;
break;
}
l[j]=i, r[j]=t;
i=t+1;
}
if(no_ans)
puts("NO");
else{
puts("YES");
for(j=1;j<=m;j++)
make(j-1,l[j],r[j]);
}
return 0;
}