【CQOI2007】【NKOJ2006】三角形

问题描述

画一个等边三角形,把三边的中点连接起来,得到四个三角形,把它们称为T1,T2,T3,T4,如图1。把前三个三角形也这样划分,得到12个更小的三角形:T11,T12,T13,T14,T21,T22,T23,T24,T31,T32,T33,T34,如图2。把编号以1,2,3结尾的三角形又继续划分……最后得到的分形称为Sierpinski三角形。这里写图片描述
如果B不包含A,且A的某一条完整的边是B的某条边的一部分,则我们说A靠在B的边上。例如T23靠在T24和T4上,但不靠在T32上。给出Spierpinski(注:原文如此)三角形中的一个三角形,找出它靠着的所有三角形。


输入格式

输入仅一行,即三角形的编号,以T开头,后面有n个1到4的数字。仅最后一个数字可能为4。


输出格式

输出每行一个三角形编号,按字典序从小到大排列。


样例输入 1

T312


样例输出 1

T314
T34
T4


样例输入 2

T123212321


样例输出 2

T123212324
T12321234
T1232124


提示

50%的数据满足:1<=n<=5
100%的数据满足:1<=n<=50


其实这道题刚开始我看的时候以为是道分治题,因为在不断分形嘛,但是后来发现其实它每一次分形都是有规律的。

我们不妨再画下一组出来,草稿本上画一画是一个好习惯。
在这里我就直接把我电脑上画的丑图放出来,解释一下规律。
这里写图片描述

从图上,我们不难找出如下规律:

  • 当输入的序列尾数为4的时候,我们只需要将它周围的三个三角形输出来即可。而周围的三个三角形满足规律:将输入的序列队尾分别改成1,2,3即可。
  • 当输入的序列尾数不为4的时候,我们可以用以下方法来求解:从后往前枚举每一位数i,若该数字没有出现过,则标记mark[i]==true,并将i以及后面的数位一起改为i。如样例输入1,T312(if(mark[2]==false))则变为T314;接着讨论mark[1],mark[3],均没有出现过,则变为T34,T4

有了这个规律,做这个题就十分简单了。

#include<iostream>   
#include<cstdio>   
#include<cstring>   
using namespace std;   
char s[100];   
int ans[100],len; 
int temp;  
int cnt=1; 
bool mark[10];   
int main()
{   
    scanf("%s",&s); 
    len=strlen(s)-1;   
    if (s[len]=='4')//讨论最后位数为4的情况 
    {   
        for(int i=1;i<=3;++i) 
        {   
            printf("T"); 
            for (int j=1;j<len;++j)  
            printf("%c",s[j]);   
            printf("%d\n",i);   
        }   
    }   
    else //如果!=4 
    {   
        ans[1]=len-1;   
        for (int i=len-2;i>=0;--i) 
        {   
            mark[s[i+2]-'0']=true;//标记过已经出现过 
            if(!mark[s[i+1]-'0'])cnt++,ans[cnt]=i; 
        }   
        for(int i=1;i<=cnt;++i) 
        {   
            printf("T"); 
            for (int j=1;j<=ans[i];++j) printf("%c",s[j]);   
            printf("%d\n",4);   
        }   
    }   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值