解析
dfs暴力枚举即可
这题的重点是如何剪枝
不难发现,随着不断处理,纸条只会越来越短,且所有数字总加和不变
我一开始想到了2个条件:
1.当前长度比理想纸条小,return;
2.总加和与理想纸条不等,直接输出N
但是这样仍是O(n!)的级别,得到了80分
后来又想到:
反转之后对后一半的与反转前对前一半的折叠是等效的,所以只需要递归一半的长度即可
从而通过本题
代码
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
#include <string>
#include<map>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a));
using namespace std;
const int N=50;
const int M=1e9;
int n,m,mod;
int a[N],b[N];
int save[N][N],save2[N][N];
int flag;
void memory(int l){
for(int i=0;i<=a[0];i++) save[l][i]=a[i];
}
void restore(int l){
for(int i=0;i<=save[l][0];i++) a[i]=save[l][i];
}
void fold(int p){
memory(a[0]);
int x=0,l=a[0];
if(p<=a[0]/2){
for(int i=save[l][0];i>=p+p+1;i--) a[++x]=save[l][i];
for(int i=1;i<=p;i++) a[++x]=save[l][i]+save[l][p+p-i+1];
a[0]-=p;
}
else{
for(int i=1;i<=2*p-a[0];i++) a[++x]=save[l][i];
for(int i=2*p-save[l][0]+1;i<=p;i++) a[++x]=save[l][i]+save[l][save[l][0]-(i-(2*p-save[l][0]))+1];
a[0]-=(a[0]-p);
}
return;
}
void memory2(int l){
for(int i=0;i<=a[0];i++) save2[l][i]=a[i];
}
void restore2(int l){
for(int i=0;i<=save2[l][0];i++) a[i]=save2[l][i];
}
void fanzhuan(){
memory2(a[0]);
for(int i=1;i<=a[0];i++) a[i]=save2[a[0]][save2[a[0]][0]-i+1];
}
bool judge(){
for(int i=0;i<=b[0];i++){
if(a[i]!=b[i]) return false;
}
return true;
}
void print(){
for(int i=1;i<=a[0];i++) printf("%d ",a[i]);
printf("\n");
}
bool jd(){
int pd[N]={},ok[N]={};
for(int i=1;i<=a[0];i++) pd[i]=a[i];
sort(pd+1,pd+1+a[0]);
for(int i=1;i<=b[0];i++) ok[i]=b[i];
sort(ok+1,ok+1+b[0]);
// for(int i=1;i<=b[0];i++){
// printf("b=%d a=%d\n",ok[i],pd[i]);
// }
for(int i=1;i<=b[0];i++){
if(ok[i]<pd[i]) return false;
}
return true;
}
void dfs(){
// print();
if(flag) return;
if(a[0]<b[0]) return;
// if(!jd()) return;
int l=a[0];
if(a[0]==b[0]){
if(judge()){
printf("S\n");flag=1;return;
}
fanzhuan();
if(judge()){
printf("S\n");flag=1;
}
restore2(l);
return;
}
for(int i=1;i<=a[0]/2;i++){
fold(i);
dfs();
if(flag) return;
restore(l);
}
fanzhuan();
for(int i=1;i<=a[0]/2;i++){
fold(i);
dfs();
if(flag) return;
restore(l);
}
restore2(l);
return;
}
int main(){
while(scanf("%d",&n)==1){
flag=0;
int tot=0;
mem(a,0);mem(b,0);
for(int i=1;i<=n;i++) mem(save[i],0);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);tot+=a[i];
}
a[0]=n;
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&b[i]);
tot-=b[i];
}
b[0]=m;
if(m>n||tot!=0){
printf("N\n");continue;
}
dfs();
if(!flag) printf("N\n");
}
return 0;
}