51NOD 1400 序列分解

传送门:序列分解

基准时间限制:1s  空间限制:131072KB
         
 

小刀和大刀是双胞胎兄弟。今天他们玩一个有意思的游戏。 大刀给小刀准备了一个长度为 $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示例
2
4
1 1 2 2
6
1 2 3 4 5 6
Output示例
Good job!!
What a pity!

分析:
暴力。DFS 递归地扩展出一棵解答树。节点(DFS)参数为 $(i, j, k)$ ,表示当前两子序列待确定 (active) 列中可
用(active) 的位置是 $k$ 。(其实 $k$ 是可有可无的参数,因为 $k = i+j-1$ ,但添上也无妨)代码中加上了一些剪枝。
不失一般性,可认为原序列的首元素属于第一个子序列,因此初始调用参数可设为 $( 2, 1, 2)$ 。

P.S. 考虑这个问题时,没想出非暴力的解法,只是看出:
如果原序列可分成两个相等的子列,那么原序列的首、尾一定也是子列的首、尾
若有更好的解法,望在评论里告知。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[50], N, x[50], y[50];
 4 bool dfs(int i, int j, int k){
 5     bool res;
 6     if(k>N) return true;
 7     if(i>N>>1){
 8         return a[k]==x[j]?y[j]=a[k], dfs(i, j+1, k+1):false;
 9     }
10     if(j>N>>1){
11         return a[k]==y[i]?x[i]=a[k], dfs(i+1, j, k+1):false;
12     }
13     if(i==j){
14         x[i]=a[k];
15         if(dfs(i+1, j, k+1)) return true;
16         y[j]=a[k];
17         return dfs(i, j+1, k+1);
18     }
19     if(i>j){
20         res = x[j]==a[k]?y[j]=a[k],dfs(i, j+1, k+1):false;
21         if(res) return res;
22         return x[i]=a[k],dfs(i+1, j, k+1);
23     }
24     if(j>i){
25         res = y[i]==a[k]?x[i]=a[k],dfs(i+1, j, k+1):false;
26         if(res) return res;
27         return y[j]=a[k],dfs(i, j+1, k+1);
28     }
29 }
30 int main(){
31     //freopen("in", "r", stdin);
32     int T;
33     scanf("%d", &T);
34     while(T--){
35         scanf("%d", &N);
36         int res=0;
37         for(int i=1; i<=N; i++) scanf("%d", a+i), res^=a[i];
38         if(res){
39             puts("What a pity!");
40             continue;
41         }
42         x[1]=a[1];
43         puts(dfs(2, 1, 2)?"Good job!!":"What a pity!");
44     }
45     return 0;
46 }

原文地址:https://www.cnblogs.com/Patt/p/4677136.html