poj1063 解题报告(poj 1063 analysis report)

题目:

一个循环序列,其中有若干0和1,两个间隔为1(即间隔一个数)的数的位置可以互换。问题是,给定一个这样的队列,判断是否可以将所有的0和1分别归拢到一起,即可以将此循环序列切断为两个序列,一个里面只有1,一个里面只有0.

思考:

题目不难,刚开始没有发现公式,考虑到的情况少了,所以wa了,后来考虑到所有情况,并总结了公式,就ac了。

证明:

引理1:相邻的两个数只有10,01,11,00 四种情况,其中00,11这两种情况对于整个循环序列没有影响。

证明:若存在11或00这两种组合,显然,通过在不同位置上执行数字互换操作(题目里所提),这种组合可以被移动到循环序列的任意指定位置。因此,当循环序列里面只有11和00时,我们可以非常简单地移动所有11(或00),让它们相连,这样循环序列就可以分成两个全0和全1的子序列。所以,11和00的存在不影响最终结果。

题目证明

1.如果循环序列的长度是奇数,那么此循环序列一定可以切断为两个序列,一个里面只有1,一个里面只有0.

证明:如果长度是奇数,那么一定有偶数个1+奇数个0,或者偶数个0+奇数个1.如果1和0的个数不相等,那么一定有11或00这种情况存在,因为n个0或1无法将n+1个1或0分开(注意,是循环序列,头和尾之间也需要插入数字分开)。又因为引理1,所以存在的00和11可以被消去,即不考虑,那么剩下的循环序列长度还是奇数,因此还存在00或11。这样一直消去,直到长度为1,长度为1的循环序列是一定满足要求的。

2.如果循环序列的长度是偶数,若0或1在偶数位上的数目与在奇数位上的数目之差小于等于1,那么此循环序列一定可以切断为两个序列,一个里面只有1,一个里面只有0.

证明:如果长度是偶数,假设里面有m个01,n个10(剩下的00和11根据引理1可以不考虑)。如果一个10和一个01相邻,则可以通过换位操作将1001变成1100。若m和n相等,则最后经过消去,没有数字剩下,因此这是个循环序列;若有m和n相差1,则最后经过消去,只剩下一个01或10,这也是一个循环序列;若m和n相差大于1,则剩下k个10或01,k>=2,例如:1010,这不是一个循环序列。所以,只有m和n的差小于等于1时,循环序列才满足题目要求。不失一般性地,设10中的1处于奇数位,01中的1处于偶数为,则只有在偶数位上的数目与在奇数位上的数目之差小于等于1时,才满足题目要求。

 

3.代码

 1 #include<stdio.h>
 2 #include<math.h>
 3 int main()
 4 {
 5     int d[30],n,c;
 6     scanf("%d",&n);
 7     while(n>0)
 8     {
 9         int ow=0,ew=0;
10         scanf("%d",&c);
11         for(int i=0;i<c;i++)
12             scanf("%d",&d[i]);
13         if(c%2==1)
14             printf("YES\n");
15         else
16         {
17             for(int i=0;i<c;i++)
18             {
19                 if(d[i]==0)
20                 {
21                     if(i%2==0)
22                         ow++;
23                     else
24                         ew++;
25                 }
26             }
27             if(abs(ow-ew)<2)
28                 printf("YES\n");
29             else
30                 printf("NO\n");
31         }
32         n--;
33     }
34     return 0;
35 }

 

 

posted @ 2013-01-17 23:18  handspeaker  阅读(555)  评论(0编辑  收藏  举报