《黑书》例题:三色多边形

http://acm.timus.ru/problem.aspx?space=1&num=1181

这是一道递归题?倒不如说是模拟题,不知道是哪个(混蛋)学长和我说的,模拟题是最容易,容易个毛线........好吧,废话不说了

思路:黑书上有它的思路P20,但我还是说说自己的想法吧。先是按照黑书的思路,要是可以将一个n边形的问题规模转化为n-1,n-2......3,也就是说可以讲符合条件的三角形切掉,然后再去找下一个符合条件的三角形,再切掉.......但是有个问题,什么时候不切了??
黑书中描述的很清楚,有一种特殊的情况,三种颜色,有一种颜色只出现一次,那么我们可以以这种颜色为顶点,分切三角形.......例如:

《黑书》例题:三色多边形
这样,就是递归的结束条件.........我的思路写的很乱,具体的还是请去看黑书的吧......
代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

char s[20000];

int a[20000],flag=0,n;

int dfs(char s[])

{

	int r,b,g;

	r=b=g=0;

	int len=strlen(s);

	for(int i=0;i<len;i++)    //这是每次都记录R\B\G出现的次数 

	{

		if(s[i]=='R')

		r++;

		if(s[i]=='B')

		b++;

		if(s[i]=='G')

		g++;

	}

	if(r==1)                //判断是否只是出现一次 

	{

		for(int i=0;i<len;i++)

		if(s[i]=='R')

		{

			int tmp;

			if(i==len-1)                 //如果只是出现一次,那么要考虑有那只出现一次的所在位置,可以是0位置,中间位置,和末位置 

			tmp=1;

			else

			tmp=0;

			for(int j=i-2;j>=tmp;j--)

			{

				printf("%d %d\n",a[i]+1,a[j]+1);

				flag++;

			}

			if(i==0)                      

			tmp=len-2;

			else

			tmp=len-1;

			for(int j=i+2;j<=tmp;j++)

			{

				printf("%d %d\n",a[i]+1,a[j]+1);

				flag++;

			}

			

		}

		return 1;                //解决完后,你会发现所以情况都考虑了,就需要返回 

	}

	else if(b==1)

	{

		for(int i=0;i<len;i++)

		if(s[i]=='B')

		{

			int tmp;

			if(i==len-1)

			tmp=1;

			else

			tmp=0;

			for(int j=i-2;j>=tmp;j--)                      //输出对角线 

			{

				printf("%d %d\n",a[i]+1,a[j]+1);

				flag++;

			}

		

			if(i==0)

			tmp=len-2;

			else

			tmp=len-1;

			for(int j=i+2;j<=tmp;j++)

			{

				printf("%d %d\n",a[i]+1,a[j]+1);

				flag++;

			}

		

		}

		return 1;

	}

	else if(g==1)

	{

		for(int i=0;i<len;i++)

		if(s[i]=='G')

		{

			int tmp;

			if(i==len-1)

			tmp=1;

			else

			tmp=0;

			for(int j=i-2;j>=tmp;j--)

			{

				printf("%d %d\n",a[i]+1,a[j]+1);

				flag++;

			}

		

			if(i==0)

			tmp=len-2;

			else

			tmp=len-1;

			for(int j=i+2;j<=tmp;j++)

			{

				printf("%d %d\n",a[i]+1,a[j]+1);

				flag++;

			}

			

		}

		return 1;

	}

	else

	{

		int i;

		for(i=0;i<len-2;i++)                            //这里,要记着-2......一开始这里木有注意..... 

		if(s[i]!=s[i+1]&&s[i]!=s[i+2]&&s[i+1]!=s[i+2])  

		{

			printf("%d %d\n",a[i]+1,a[i+2]+1);       //输出可以的对角线 

			flag++;

			for(int j=i+1;j<len-1;j++)         //将那个对角线里面的点过滤掉,但是不能改变剩下的点的位置和颜色 ,一开始我就是不知道这里怎么实现的 

			{

				s[j]=s[j+1];                 //看了大神代码之后,就明白了.......就是把那个店过滤,用后面的点覆盖那个点,颜色与位置都做这样的操作 

				a[j]=a[j+1];

			}

			s[len-1]='\0';                //就是这里,wa了2次.......一定要注意,把点覆盖后,要将它末尾置为结束符 

			

			break;                     

		}

	}

	if(dfs(s))

	return 1;

	return 0;

}

int main()

{

	while(scanf("%d",&n)>0)

	{

		scanf("%s",s);

		int r=0,b=0,g=0,w=0;

		int len=strlen(s);

		if(s[0]==s[len-1]) {printf("0\n"); continue;}  //这里wa了一次,第一个字符与最后一个字符是相邻的,但我一开始没有考虑到它们是否相等 

		for(int i=0;i<len-1;i++)

		if(s[i]==s[i+1])

		{

			w=1;

			break;

		}

		for(int i=0;i<len;i++)

		{

			if(s[i]=='R')

			r++;

			if(s[i]=='B')

			b++;

			if(s[i]=='G')

			g++;

		}

		if(w==1||r==0||b==0||g==0)   //要是R\B\G有为0的,说明肯定有相邻相等的..... 

		{

			printf("0\n");

			continue;

		}

		for(int i=0;i<n;i++)

		a[i]=i;

		printf("%d\n",n-3);        //将多边形分为n-2个三角形,必然要n-3条边 

		flag=0;

		dfs(s);

	}

	return 0;

} 

 

你可能感兴趣的:(书)