《黑书》例题:三色多边形
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;
}
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。

浙公网安备 33010602011771号