老曹的忧郁

老曹的忧郁

Time Limits: 1000 ms Memory Limits: 65536 KB Detailed Limits

Description
  我们的主角——老曹,现在十分忧郁。原因是他在玩一个困难的游戏。
  游戏规则如下:

  有(N+1)*n/2个圆盘,在平面上摆成了一个变长为N个圆盘的等边三角形。每个圆盘上标有一个小写字母(‘a’_’z’),如下图所示。 
  对于每个字母,当我们可以由标为这个字母的圆盘为顶点,构成等边三角形时,我们称这个字母为不和谐的。例如图中的a和c。

字母等边三角形
  现在给你N和这个等边三角形上的字母,要求哪些字母是不和谐的。

Input
  第一行:一个整数,N(1<=N<=12)
  第二行:(N+1)*N/2个小写字母

Output
  一行:按字典序输出所有不和谐的字母,如果没有不和谐的字母,则输出“Harmonious”。

Sample Input
Input1:

3
aaaaaa

Input2:

3
abcdef

Sample Output
Output1:

a

样例输出2:

Harmonious

解题思路

其实这道题很简单,直接建立坐标系,令等边三角形的顶点(最顶端的圆的圆心)是(0,0),圆形的直径为2就可以了。

假设一个圆的圆心为(x,y)那么有如下规律:

  1. 它同一层左边的点为(x-2,y)
  2. 它同一层右边的点为(x+2,y)
  3. 它下一层左边的点为(x-1,y- 3 )
  4. 它下一层左边的点为(x+1,y- 3 )

最后直接暴力同一个字母的三个点,判断是否是等边三角形即可。

如果你不愿意打real类型,你只用存 3 的系数就可以了,也就是说,你在存 23 时就存着2就行了,不过最后求距离是要把
sqrt((x1-x2)^2+(y1-y2)^2);写成sqrt((x1-x2)^2+3(y1-y2)^2);就可以了

Codes:
type
    int=shortint;
    rec=record
        num:int;
        loca:array[1..78,1..2]of shortint;
    end;
var
    le:array['a'..'z']of rec;
    n,i,j,k:int;
    c:char;
    x,y,xx,yy,z:int;
    p,q:boolean;

{求两点的距离}
function Get_Distance(x1,y1,x2,y2:int):int;
    begin exit((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)*3);end;

{求一个圆的左下角的圆的圆心的坐标}
procedure Get_Left_Point(x,y:int;var ansx,ansy:int);
    begin ansx:=x-1;ansy:=y-1;{存sqrt(3)的系数}end;

{Judge 判断是否有同一字母的三个点构成等边三角形}
function can(w:char):boolean;
begin
    with le[w] do
        for i:=1 to num-2 do
            for j:=i+1 to num-1 do
                for k:=j+1 to num do
                begin{这里不用想的那么复杂,暴力就好了}
                    x:=Get_Distance(loca[i,1],loca[i,2],loca[j,1],loca[j,2]);
                    y:=Get_Distance(loca[i,1],loca[i,2],loca[k,1],loca[k,2]);
                    z:=Get_Distance(loca[k,1],loca[k,2],loca[j,1],loca[j,2]);
                    if(x=y)and(y=z)then exit(true);
                end;
    exit(false);
end;

{Main}
begin
    p:=false;
    readln(n);
    x:=0;y:=0;read(c);
    with le[c] do
    begin
        inc(num);loca[num,1]:=x;loca[num,2]:=y;
    end;
    for i:=2 to n do
    begin
        read(c);Get_Left_Point(x,y,xx,yy);
        with le[c] do
        begin
            inc(num);loca[num,1]:=xx;loca[num,2]:=yy;
        end;
        x:=xx;y:=yy;
        for j:=2 to i do
        begin
            xx:=xx+2;read(c);
            with le[c] do
            begin
                inc(num);loca[num,1]:=xx;loca[num,2]:=yy;
            end;
        end;
    end;
    for c:='a'to'z'do
        if le[c].num>2 then
        begin
            q:=can(c);p:=p or q;
            if q then write(c);
        end;
    if not p then writeln('Harmonious');
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值