注意点蛮多的。。。数列大小一定是先上升后下降的,也就是“^”形状。所以可以分成左右两部分s1,s2。注意剪枝。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
#include <assert.h>
using namespace std;
int n;
int sum[1003], x[1003];
bool vis[1003][(1 << 13) + 1];
char ans[1003];
int highBit[1 << 14];
int dfs(int p,int s1){
int s2=(p==0?0:sum[p-1])-s1;
if(p==n){
if(s1==highBit[s1]&&s2==highBit[s2]&&(s1+s2)==highBit[s1+s2]){
return 1;
}
return 0;
}
if(vis[p][s1]||vis[p][s2])
return 0;
vis[p][s1]=1;
vis[p][s2]=1;
int u=14,uu=0,a,b;
for(int i=0;i<=13;++i){
if(s1&(1<<i)){
u=i;
break;
}
}
if((1<<u)>=x[p]){
a=s1+x[p];b=s2;
if(highBit[a]==highBit[b])
a-=highBit[a],b+=highBit[a]; //判断向左/右推的时候s1最高点和s2最高点会不会合并
if(dfs(p+1,a)==1)
ans[p]='l',uu=1;
}
else if(s2==highBit[s2]&&s2>=highBit[s1]){
a=s1+s2;b=x[p];
if(highBit[a]==highBit[b])
a+=highBit[a],b-=highBit[a]; //判断向左/右推的时候s1最高点和s2最高点会不会合并
if(dfs(p+1,a)==1)
ans[p]='r',uu=1;
}
u=14;
for(int i=0;i<=13;++i){
if(s2&(1<<i)){
u=i;
break;
}
}
if((1<<u)>=x[p]){
a=s1;b=s2+x[p];
if(highBit[a]==highBit[b])
a+=highBit[a],b-=highBit[a]; //判断向左/右推的时候s1最高点和s2最高点会不会合并
if(dfs(p+1,a)==1)
ans[p]='r',uu=1;
}
else if(s1==highBit[s1]&&s1>=highBit[s2]){
a=x[p];b=s1+s2;
if(highBit[a]==highBit[b])
a-=highBit[a],b+=highBit[a]; //判断向左/右推的时候s1最高点和s2最高点会不会合并
if(dfs(p+1,a)==1)
ans[p]='l',uu=1;
}
if(uu==1)
return 1;
else
return 0;
}
int main(){
for (int i=1;i<(1<<14);i++)
if ((i & -i) == i) highBit[i] = i;
else highBit[i] = highBit[i - 1];
int t;
cin>>t;
while(t--){
cin>>n;
for (int i = 0; i < n; i ++)
memset(vis[i], 0, sizeof vis[i]);
for(int i=0;i<n;++i)
cin>>x[i];
sum[0]=x[0];
for(int i=1;i<n;++i)
sum[i]=sum[i-1]+x[i];
if(dfs(0,0)){
ans[n]='\0';
printf("%s\n", ans);
}
else
cout<<"no"<<endl;
}
return 0;
}