51nod round3# 序列分解(折半枚举+字典树)

来源:互联网 发布:sql语句高级查询 编辑:程序博客网 时间:2024/05/18 22:12

小刀和大刀是双胞胎兄弟。今天他们玩一个有意思的游戏。 大刀给小刀准备了一个长度为n的整数序列。小刀试着把这个序列分解成两个长度为n/2的子序列。

这两个子序列必须满足以下两个条件:

1.他们不能相互重叠。

2.他们要完全一样。

如果小刀可以分解成功,大刀会给小刀一些糖果。

然而这个问题对于小刀来说太难了。他想请你来帮忙。


Input
第一行给出一个T,表示T组数据。(1<=T<=5)接下来每一组数据,输入共2行。第一行包含一个整数n (2<=n<=40且为偶数)。第二行给出n个整数a[0],a[1],a[2],…,a[n-1]表示大刀给小刀准备的序列。(-1,000,000,000<=a[i]<=1,000,000,000)
Output
如果小刀可以完成游戏,输出"Good job!!" (不包含引号),否则 输出"What a pity!" (不包含引号)。
Input示例
241 1 2 261 2 3 4 5 6
Output示例
Good job!!What a pity!




思路:把原来的串分成两半。然后前半段枚举哪些给第一个序列,剩下的给第二个序列,从前往后匹配,如果有一个串是另外一个串的前缀,那么把剩下的后缀插入到字典树中。否则不插入。

然后枚举后半段。这个时候要有一个串是另外一个串的后缀,然后拿剩下的前缀去字典树里面查询。如果有的话,说明成功。而且先要离散化一下

复杂度是  $O\left( {{\rm{n*}}{{\rm{2}}^{n/2}}} \right)$ 


//Accepted 375 ms 96120 KB#include <iostream>#include <cstring>#include <cmath>#include <queue>#include <stack>#include <list>#include <map>#include <set>#include <sstream>#include <string>#include <vector>#include <cstdio>#include <ctime>#include <bitset>#include <algorithm>#define SZ(x) ((int)(x).size())#define ALL(v) (v).begin(), (v).end()#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)#define refeach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i)#define REP(i,n) for ( int i=1; i<=int(n); i++ )using namespace std;typedef long long ll;const int N = 1<<18;struct node{    node* child[45];    bool flag;    node()    {        memset(child,0,sizeof(child));        flag = 0;    }}trie[N];int sz;node *root,*cur;node* createnode(){    memset(trie[sz].child,0,sizeof(trie[sz].child));    trie[sz].flag = 0;    return &trie[sz++];}void Insert(int s[],int L,int R){    cur = root;    for(int p = L; p <= R; p++)    {        int val = s[p] ;        if(cur->child[val] == NULL )            cur->child[val] = createnode();        cur = cur->child[val];    }    cur->flag = 1;}bool query(int s[],int L,int R){    cur = root;    for(int p = R;p >= L; p--)    {        int val = s[p];        if(cur->child[val] == NULL) return false;        cur = cur->child[val];    }    return cur->flag;}pair<int,int>b[50];int a[50];int s1[50],s2[50];int top1,top2;int main(){    int T;    cin>>T;    while(T--)    {        sz = 0;        root = createnode();        int n;        scanf("%d",&n);        REP(i,n) scanf("%d",&b[i].first),b[i].second = i;        sort(b+1,b+1+n);        int maxx = 0;        a[b[1].second] = maxx;        for(int i = 2 ; i<= n ; i++)            if(b[i].first == b[i-1].first) a[b[i].second] = maxx;            else a[b[i].second] = ++maxx;        for(int mask = 0; mask < (1<<n/2) ; mask++)        {            top1 = top2 =0;            int i;            for(i = 0; i < n/2; i++)            {                if(mask&(1<<i))                {                    s1[++top1] = a[i+1];                    if(top1 <= top2 && s1[top1] != s2[top1]) break;                }                else                {                    s2[++top2] = a[i+1];                    if(top2 <= top1 && s1[top2] != s2[top2]) break;                }            }            if(i == n/2)            {                if(top1 <= top2) Insert(s2,top1+1,top2);                else Insert(s1,top2+1,top1);            }        }        bool KO = 0;        for(int mask = 0; mask < (1<<n/2) && KO == 0; mask++)        {            top1 = top2 = 0;            int i;            for(i = 0; i < n/2; i++)            {                if(mask&(1<<i))                {                    s1[++top1] = a[n-i];                    if(top1 <= top2 && s1[top1] != s2[top1]) break;                }                else                {                    s2[++top2] = a[n-i];                    if(top2 <= top1 && s1[top2] != s2[top2]) break;                }            }            if(i == n/2)            {                if(top1 <= top2 && query(s2,top1+1,top2)) KO = 1;                else if(top1 > top2 && query(s1,top2+1,top1)) KO = 1;            }        }        if(KO) puts("Good job!!");        else puts("What a pity!");    }    return 0;}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 如果有人要砍我怎么办 美版手机坏了怎么办 战地4ping太高怎么办 喝了红牛睡不着怎么办 球球大作战总是闪退怎么办解决方法 球球大作战手机号己绑定怎么办 弄的底窝中药味太大怎么办 锤子手机上不了网怎么办 ppt没保存就卡了怎么办 ppt卡了没保存怎么办 匡威鞋舌头跑偏怎么办 霍尼韦尔dcs cb锁死怎么办 谷歌身份验证器丢失 怎么办 叛乱2手雷没了怎么办 王者转移号封了怎么办? 电脑被入侵挖矿怎么办 我把exe删除了怎么办 大学图书馆借书超过期限了怎么办 win10更新完鼠标没有了怎么办 打开软件提示运行出错怎么办 电脑中了u盘病毒怎么办 电脑中病毒自动重启怎么办 病毒软件不断发信息买服务怎么办 qq被腾讯屏蔽了怎么办 电脑被u盘中毒怎么办 电脑一分钟重启怎么办 创维电视音量小怎么办 捷豹pin码忘记了怎么办 华为手机版本更新下载不了怎么办? 微信钱包没有钱怎么办 微信钱包里没有钱怎么办 微信没有收到退款怎么办 微信转账退款没有收到怎么办 礼物跟人家送重复怎么办 你已被steam封禁怎么办 武装突袭3被锁定怎么办 绝地求生右下角小地图变大怎么办 ctrl z 误删了怎么办 武装突袭3渴了怎么办 武装突袭3枪卡壳怎么办 玩武装突袭3CPU不好怎么办?