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... 加个剪纸过了. 这题数据水.可以构造数据来卡主.
折半枚举 前半段和后半段分别选出 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;
}
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;
}
相关文章推荐
- 51nod-序列分解(dfs)
- 51nod oj 1400 序列分解 【dfs暴力】
- 51nod 1400 序列分解(DFS + 剪枝)
- 51nod round3# 序列分解(折半枚举+字典树)
- 51nod 1400 序列分解【Dfs+剪枝】好题~
- 51 nod 1400 序列分解(dfs+剪枝)@
- 51nod 算法马拉松3 A:序列分解
- 51nod 1400 序列分解 阻止我的只有读题能力了
- 51nod 算法马拉松3 A:序列分解
- 【51nod 1126】求递推序列的第N项 【矩阵快速幂】or【枚举找循环节】
- 51Nod-1400-序列分解
- 51nod 1400 序列分解(深搜)
- 51nod 40 选择子序列 单调栈+DP
- 【2016杭电女生赛1005】【暴力 bfs or dfs or 模拟】girlcat 数女生数和猫咪数
- 【HDU5536 2015长春赛区 J】【字典树or暴力】Chip Factory 字典序做法+暴力做法
- 51nod 1489 蜥蜴和地下室 暴力dfs
- 51NOD 1400 序列分解
- 【hautoj 1281】邪能炸弹 【DFS 暴力】or 【DP】
- Light OJ 1049 - One Way Roads (暴力 or DFS)
- 51Nod-1489 蜥蜴和地下室(暴力DFS)