老曹的忧郁

来源:互联网 发布:离线翻译软件 知乎 编辑:程序博客网 时间:2024/05/01 16:30

老曹的忧郁

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:

3aaaaaa

Input2:

3abcdef

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