[Virtual Judge]URAL1181:Cutting a Painted Polygon

来源:互联网 发布:软件开发咨询合同 编辑:程序博客网 时间:2024/04/29 03:48

点击打开题目链接

1181. Cutting a Painted Polygon

Time limit: 1.0 second
Memory limit: 64 MB
There is a convex polygon with vertices painted in three colors: Red (R), Green (G) and Blue (B). It is known that all the colors are present and any two neighbor vertices have different colors. You are to find out whether it is possible to cut this polygon with noncrossing diagonals so that each of the obtained triangles would have all vertices of different colors: one red, one green and one blue vertex. Point out a possible way of the cutting if the cutting is possible.

Input

The first line contains a number N of the polygon vertices (4 ≤ N ≤ 1000). There are N symbols of the set {'R', 'G', 'B'} in the second line that specify a color for the correspondent vertex.

Output

The first line should contain either a number of drawn diagonals in case the required cutting is possible or the number 0 otherwise (cutting is impossible). In the first case the following lines should contain a description of the drawn diagonals. The description of a diagonal takes one line and consists of diagonal vertices numbers. The numbers are separated with a space. If there are several possible cuttings that satisfy the requirements you may output any of them.

Sample

inputoutput
7RBGBRGB
41 33 75 75 3


=====================================题目大意=====================================


给定一个顶点颜色为红绿蓝三者之一且相邻顶点颜色不同的N边形。

输出任意一种通过不交叉的对角线将该多边形划分为各个顶点颜色不同的三角形的方案。

如果不存在这样的方案则输出0。


=====================================算法分析=====================================


分治算法(此题即黑书P20:三色多边形)。


本来就想写上面那一句话,结果最后忍不住又写了下面一大堆证明。。。


引入定义:1、将一个有C(C>=2)种不同颜色顶点且相邻顶点颜色不同的凸N(N>=3)边形称为C色顶点相间N边形,记为Polygon(C,N)。

          2、将Polygon(C,N1)通过不交叉的对角线划分为Polygon(C,N2)(N1>N2>=4)的过程称为C色顶点相间多边形的N2至N1划分,

             记为Divide(C,N1_N2)。

那么就有:本题即求给定Polygon(3,N)的Divide(3,N_3)。

定理证明:1、当N=4时,显然对于任意的Polygon(3,N)总存在有Divide(3,N_3)。

          2、令N=K时,对于任意的Polygon(3,K)总存在有Divide(3,K_3)。

             因为任意一个Polygon(3,K+1)总可以通过一个Polygon(3,K)与一个Polygon(3,3)组合得到。

             所以任意一个Polygon(3,K+1)总存在Divide(3,K+1_K),进而任意一个Polygon(3,K+1)总存在Divide(3,K+1_3)。

             综合可得(数学归纳法):任意一个Polygon(3,N)总存在Divide(3,N_3)。

从而可知:解决问题的方法就是将Polygon(3,N)进行Divide(3,N_N-1)得到Polygon(3,N-1),循环直到N==3。

ByTheWay:Divide(3,N_N-1)的具体方法是找到连续的三个颜色各不相同的顶点,将边上的两个顶点的连线作为划分线。

          当Polygon(3,N)的某个顶点颜色唯一时,由于Divide(3,N_N-1)后得到的Polygon(3,3)和Polygon(3,N-1)都必须包含此顶

          点(不然哪还有三色),

          所以此顶点必须位于划分线上,而其后的所有划分也如此。也就如同黑书所说,此时通过该颜色唯一的顶点向其他各顶点

          做划分线即可。

举例说明:测试样例1的划分过程如下所示。


          


=======================================代码=======================================



#include<stdio.h>#include<string.h>int N,RGBVS[3];                                            //Red Green Blue Vertice Sumstruct VERTICE { int colour; int next; } Memory[1005];void DivideAndConquer(){int Cur=0;while((RGBVS[0]-1)&&(RGBVS[1]-1)&&(RGBVS[2]-1))        //循环直到某种颜色的顶点数为1{int Next1=Memory[Cur].next;                        //当前顶点的下一个顶点int Next2=Memory[Next1].next;                      //当前顶点的下下个顶点if(Memory[Cur].colour!=Memory[Next2].colour)       //在相邻顶点颜色不同的条件下,只需P与Next2颜色不同即得P,Next1,Next2颜色均不同{    printf("%d %d\n",Cur+1,Next2+1);               //选取分割线(P,Next2)Memory[Cur].next=Next2;                        //删除顶点Next1--RGBVS[Memory[Next1].colour];                 //相应颜色的顶点数减少}Cur=Memory[Cur].next;}while(RGBVS[Memory[Cur].colour]-1)                     //找到颜色唯一的顶点{Cur=Memory[Cur].next;}while(1){int Next1=Memory[Cur].next;                        //当前顶点的下一个顶点int Next2=Memory[Next1].next;                      //当前顶点的下下个顶点if(Cur==Memory[Next2].next) { break; }             //循环直到多边形成为三角形printf("%d %d\n",Cur+1,Next2+1);                   //选取分割线(P,Next2)Memory[Cur].next=Next2;                            //删除顶点Next1}}void ReaData(){char Polygon[1005];scanf("%s",Polygon);memset(RGBVS,0,sizeof(RGBVS));for(int i=0;Polygon[i];++i){if(Polygon[i]=='R')      { Memory[i].colour=0; ++RGBVS[0]; }else if(Polygon[i]=='G') { Memory[i].colour=1; ++RGBVS[1]; }else if(Polygon[i]=='B') { Memory[i].colour=2; ++RGBVS[2]; }Memory[i].next=(i+1==N?0:i+1);}}int main(){while(scanf("%d%*c",&N)==1){ReaData();printf("%d\n",N-3);DivideAndConquer();}return 0;}