51nod 40 序列分解 暴力dfs or 折半+字典树
来源:互联网 发布:中日韩总体实力知乎 编辑:程序博客网 时间:2024/05/24 20:08
题意:长度为n的序列a,从a中选出两个长度为n/2的子序列b,c.a中每个元素要么属于b要么属于c.
2<=n<=40 -1e9<=a[i]<=1e9 问是否存在子序列b等于子序列c?
初始序列b,c都为空 假如a[1]属于序列b. 那么下一个x=a[1]的数可能属于序列c 中间的数肯定都压入序列b中
若序列b长度大于n/2,无解.
14
1 7 10 1 7 4 5 7 1 10 7 4 5 1
WAWAWA... 按上面算法来执行则无解 实际上有{1,7,10,7,4,5,1}第5个7选给了序列b.
暴力来匹配. TLE... 加个剪纸过了. 这题数据水.可以构造数据来卡主.
折半枚举 前半段和后半段分别选出 A,B,C,D
若B为A的前缀,则把A剩下部分压入字典树.
2<=n<=40 -1e9<=a[i]<=1e9 问是否存在子序列b等于子序列c?
初始序列b,c都为空 假如a[1]属于序列b. 那么下一个x=a[1]的数可能属于序列c 中间的数肯定都压入序列b中
若序列b长度大于n/2,无解.
14
1 7 10 1 7 4 5 7 1 10 7 4 5 1
WAWAWA... 按上面算法来执行则无解 实际上有{1,7,10,7,4,5,1}第5个7选给了序列b.
暴力来匹配. TLE... 加个剪纸过了. 这题数据水.可以构造数据来卡主.
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=2e4+5;int T,n,a[N],b[N],c[N]; bool flag;void dfs(int x,int now,int pb,int pc){if(pb>n/2||flag)return;if(x==n+1){if(pc==n/2)flag=true;return;}if(a[x]==b[now]&&pc<pb)dfs(x+1,now+1,pb,pc+1);b[++pb]=a[x];dfs(x+1,now,pb,pc);}int main(){int T;cin>>T;while(T--){flag=false;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);b[1]=a[1];dfs(2,1,1,0);puts(flag?"Good job!!":"What a pity!");}return 0;}
折半枚举 前半段和后半段分别选出 A,B,C,D
若B为A的前缀,则把A剩下部分压入字典树.
若D为C的后缀,则把查询C是否能在字典树上匹配 若能,则得到一解:A+D=B+C.
写的半天 然后还TLE了。。。
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=40;int T,n,a[N],id[N],b[N],c[N]; int ch[N*20][20],sz;bool num[N*20];map<int,int> mp;void init(){memset(ch[0],0,sizeof(ch[0]));memset(num,0,sizeof(num));sz=1;mp.clear();}void insert(string s){int u=0;for(int i=0;s[i];i++){int c=s[i]-'a';if(!ch[u][c]){memset(ch[sz],0,sizeof(ch[sz]));ch[u][c]=sz++;}u=ch[u][c];}num[u]=1;}int find(string s){int u=0;for(int i=0;s[i];i++){int c=s[i]-'a';if(!ch[u][c])return 0;u=ch[u][c];}return num[u]==1;}int main(){int T;cin>>T;while(T--){int num=0;init();bool flag=false;scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d",&a[i]);if(!mp[a[i]])mp[a[i]]=num+1,id[i]=num++;elseid[i]=mp[a[i]]-1;}if(num>n/2){printf("%s\n","What a pity!");continue;}for(int i=0;i<(1<<(n/2));i++){int pb=0,pc=0;for(int j=0;j<n/2;j++){if((i>>j)&1)b[pb++]=id[j];elsec[pc++]=id[j];}if(pb<pc)swap(b,c),swap(pb,pc);int j;for(j=0;j<pc;j++)if(b[j]!=c[j])break;if(j==pc){string s="";for(;j<pb;j++)s+='a'+b[j];insert(s);}}for(int i=0;i<(1<<(n/2))&&flag==false;i++){int pb=0,pc=0;for(int j=0;j<n/2;j++){if((i>>j)&1)b[pb++]=id[n/2+j];elsec[pc++]=id[n/2+j];}if(pb<pc)swap(b,c),swap(pb,pc);int j,k=pb-pc;for(j=0;j<pc;j++,k++)if(b[k]!=c[j])break;if(j==pc){string s="";for(j=0;j<pb-pc;j++)s+='a'+b[j];if(find(s))flag=true;}}if(flag)printf("%s\n","Good job!!");elseprintf("%s\n","What a pity!");}return 0;}
阅读全文