您的位置:首页 > 其它

51nod 40 序列分解 暴力dfs or 折半+字典树

2017-12-25 13:48 543 查看
题意:长度为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... 加个剪纸过了. 这题数据水.可以构造数据来卡主.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e4+5;
int T,n,a
,b
,c
;
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
,id
,b
,c
;
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++;
else
id[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++)

4000
{
if((i>>j)&1)
b[pb++]=id[j];
else
c[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];
else
c[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!!");
else
printf("%s\n","What a pity!");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: