CSP-S 2021 T3 回文
传送门
不多BB直接上思路
20分思路
暴力枚举每一次操作,然后就没有然后了
40分思路
考虑在暴力枚举中优化
我们发现
一、当放入的数字在b的右半段时,只有当这个数字与与之对称的左半段数字相等时,才能放入
二、在b的同一半段中,每个数字只能出现一次
喜闻乐见的代码(40分)
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxn = 1e6 + 100;
int T;
int n;
int a[maxn];
char ans[maxn];
int tot;
int lefta,righta,totb;
bool book = 0;
bool left[maxn], right[maxn];
int b[maxn];
bool check(){
for(int i = 1;i <= n;i++){
if(b[i] != b[2 * n + 1 - i])return false;
}
return true;
}
void dfs(int now){
if(book)return;
if(now > 2 * n){
if(check()){
for(int i = 1;i < tot;i++){
putchar(ans[i]);
}
putchar('\n');
book = 1;
return;
}
return;
}
//L
if((tot <= n && left[a[lefta]] == 0)){
ans[tot] = 'L';
b[totb] = a[lefta];
left[a[lefta]] = 1;
lefta++;totb++;
tot++;
dfs(now + 1);
tot--;
ans[tot] = 0;
b[totb] = 0;
lefta--;totb--;
left[a[lefta]] = 0;
}
else if(tot > n && a[lefta] == b[2 * n + 1 - totb] && right[a[lefta]] == 0){
ans[tot] = 'L';
b[totb] = a[lefta];
right[a[lefta]] = 1;
lefta++;totb++;
tot++;
dfs(now + 1);
tot--;
ans[tot] = 0;
b[totb] = 0;
lefta--;totb--;
right[a[lefta]] = 0;
}
//R
if((tot <= n && left[a[righta]] == 0)){//
ans[tot] = 'R';
left[a[righta]] = 1;
tot++;
b[totb] = a[righta];
righta--;totb++;
dfs(now + 1);
tot--;
ans[tot] = 0;
b[totb] = 0;
righta++;totb--;
left[a[righta]] = 0;
}
else if(tot > n && a[righta] == b[2 * n + 1 - totb] && right[a[righta]] == 0){
ans[tot] = 'R';
right[a[righta]] = 1;
tot++;
b[totb] = a[righta];
righta--;totb++;
dfs(now + 1);
tot--;
ans[tot] = 0;
b[totb] = 0;
righta++;totb--;
right[a[righta]] = 0;
}
}
void percent_40(){
while(T--){
memset(left,0,sizeof(left));
memset(right,0,sizeof(right));
book = 0;
tot = 1;
scanf("%d",&n);
righta = n * 2;
lefta = 1;
totb = 1;
for(int i = 1;i <= n * 2;i++){
scanf("%d",&a[i]);
}
dfs(1);
if(book == false){
puts("-1");
}
}
}
int main(){/*
freopen("palin.in","r",stdin);
freopen("palin.out","w",stdout);*/
scanf("%d",&T);
percent_40();
return 0;
}
/*
2
5
4 1 2 4 5 3 1 2 3 5
3
3 2 1 2 1 3
*/
100分
当我们将第一个数字拿出时,其实最后一个数字已经确定了,以此类推,我们就可以得出答案
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxn = 1e6 + 100;
int T;
int n;
int a[maxn];
char ans[maxn];
int s[maxn];
int first[maxn],second[maxn];
int tp, pt;
bool check(int x,int l,int r,int y){//[x,y] as a ;[l,r] as b
if(x == l && r == y)return 1;//finished
if(x > l || r > y)return 0;//no solution
if(a[x] == a[l - 1] && check(x + 1,l - 1,r,y)){
ans[++tp] = 'L';
return 1;
}
if(a[x] == a[r + 1] && check(x + 1,l,r + 1,y)){
ans[++tp] = 'L';
return 1;
}
if(a[y] == a[l - 1] && check(x,l - 1,r,y - 1)){
ans[++tp] = 'R';
return 1;
}
if(a[y] == a[r + 1] && check(x,l,r + 1,y - 1)){
ans[++tp] = 'R';
return 1;
}
return 0;
}
int main(){
scanf("%d",&T);
while(T--){
pt = tp = 0;
scanf("%d",&n);
n *= 2;
for(int i = 1;i <= n;i++){
scanf("%d",&a[i]);
if(first[a[i]] == 0)first[a[i]] = i;
else second[a[i]] = i;
}
if(check(2,second[a[1]],second[a[1]],n)){//first as L
ans[++tp] = 'L';
int x = 1,y = n;
while(tp){
if(ans[tp] == 'L') s[++pt] = a[x++];
else s[++pt] = a[y--];
putchar(ans[tp--]);
}
while(pt){
if(a[x] == s[pt]){
putchar('L');
x++;
}
else{
putchar('R');
y--;
}
--pt;
}
}
else if(check(1,first[a[n]],first[a[n]],n - 1)){//first as R
ans[++tp] = 'R';
int x = 1,y = n;
while(tp){
if(ans[tp] == 'L') s[++pt] = a[x++];
else s[++pt] = a[y--];
putchar(ans[tp--]);
}
while(pt){
if(a[x] == s[pt]){
putchar('L');
x++;
}
else{
putchar('R');
y--;
}
--pt;
}
}
else printf("-1");//no solution
putchar('\n');
for(int i = 1;i <= n;i++){
first[i] = second[i] = 0;
}
}
return 0;
}
/*
2
5
4 1 2 4 5 3 1 2 3 5
3
3 2 1 2 1 3
*/