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

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;
} 

 

posted @ 2013-05-21 19:32  紫忆  阅读(375)  评论(0编辑  收藏  举报