https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4943
注意点蛮多的。。。数列大小一定是先上升后下降的,也就是“^”形状。所以可以分成左右两部分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; }