Problem:
三角形と円

平面上にある三角形と円の位置関係を判定するプログラムを作成してください。対象となる図形はいずれも境界を含むものとします。
三角形は 3 頂点の位置が与えられ、円は中心の位置と半径が与えられます。位置は直交座標系による２つの整数の組によって与えられます。半径も整数で与えられます。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロふたつの行で示されます。
各データセットは以下の形式で与えられます。

x1 y1
x2 y2
x3 y3
xc yc
r

１行目から３行目に、三角形の第 i の頂点座標 xi, yi が与えられます。４行目に円の中心の座標 xc, yc、５行目に円の半径 r が与えられます。与えられる入力はすべて、1 以上 10,000 以下の整数とします。

データセットの数は 100 を超えません。

Output

入力データセットごとに以下の形式で判定結果を１行に出力します。

円が三角形に含まれる場合 a

三角形が円に含まれる場合 b

それ以外の場合で、共通部分がある場合には c

共通部分がない場合には d

Sample Input

1 1
3 1
3 3
3 2
3
3 12
9 3
11 12
8 7
5
15 3
17 7
22 5
7 6
4
6 11
8 2
16 9
10 8
2
0 0

Output for the Sample Input

b
c
d
a

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            StringBuilder sb = new StringBuilder();

            while (true)
            {
                double[] input = Array.ConvertAll(Console.ReadLine().Split(' '), double.Parse);

                if (input.All(n => n == 0)) break;

                Point a = new Point(input[0], input[1]);
                input = Array.ConvertAll(Console.ReadLine().Split(' '), double.Parse);
                Point b = new Point(input[0], input[1]);
                input = Array.ConvertAll(Console.ReadLine().Split(' '), double.Parse);
                Point c = new Point(input[0], input[1]);
                input = Array.ConvertAll(Console.ReadLine().Split(' '), double.Parse);
                Point p = new Point(input[0], input[1]);
                double r = double.Parse(Console.ReadLine());

                double pa = (a - p).Abs;
                double pb = (b - p).Abs;
                double pc = (c - p).Abs;

                if (pa <= r && pb <= r && pc <= r)
                {
                    sb.AppendLine("b");
                }
                else
                {
                    if (IsPInside(a, b, c, p))
                    {
                        sb.AppendLine(CheckPIn(a, b, c, p, r));
                    }
                    else
                    {
                        sb.AppendLine(CheckPOut(a, b, c, p, r));
                    }
                }
            }
            Console.Write(sb);
        }

        static bool IsPInside(Point a, Point b, Point c, Point p)
        {
            double c1 = (b - a).Cross(p - b);
            double c2 = (c - b).Cross(p - c);
            double c3 = (a - c).Cross(p - a);

            if (c1 > 0 && c2 > 0 && c3 > 0) return true;
            if (c1 < 0 && c2 < 0 && c3 < 0) return true;
            return false;
        }

        static string CheckPIn(Point a, Point b, Point c, Point p, double r)
        {
            double lp1 = GetDistSP(a, b, p);
            double lp2 = GetDistSP(b, c, p);
            double lp3 = GetDistSP(c, a, p);

            if (lp1 >= r && lp2 >= r && lp3 >= r) return "a";
            
            return "c";
        }

        static string CheckPOut(Point a, Point b, Point c, Point p, double r)
        {
            double lp1 = GetDistSP(a, b, p);
            double lp2 = GetDistSP(b, c, p);
            double lp3 = GetDistSP(c, a, p);

            if (lp1 > r && lp2 > r && lp3 > r) return "d";

            return "c";
        }

        static double GetDistSP(Point a, Point b, Point p)
        {
            if ((b - a).Dot(p - a) < 0.0) return (p - a).Abs;
            if ((a - b).Dot(p - b) < 0.0) return (p - b).Abs;
            return GetDistLP(a, b, p);
        }

        static double GetDistLP(Point a, Point b, Point p)
        {
            return Math.Abs((b - a).Cross(p - a) / (b - a).Abs);
        }
    }

    struct Point : IComparable
    {
        static readonly double EPS = 1E-10;

        internal double x, y;

        public Point(double x, double y)
        {
            this.x = x;
            this.y = y;
        }

        public double Abs { get { return Math.Sqrt(Norm); } }
        public double Norm { get { return x * x + y * y; } }

        public double Dot(Point p) { return x * p.x + y * p.y; }
        public double Cross(Point p) { return x * p.y - y * p.x; }
        public double Distance(Point p) { return (this - p).Abs; }

        public static Point operator +(Point a, Point b) { return new Point(a.x + b.x, a.y + b.y); }
        public static Point operator -(Point a, Point b) { return new Point(a.x - b.x, a.y - b.y); }
        public static Point operator *(Point p, double d) { return new Point(p.x * d, p.y * d); }
        public static Point operator *(Point a, Point b) { return new Point(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); }
        public static Point operator /(Point p, double d) { return new Point(p.x / d, p.y / d); }
        public static bool operator <(Point a, Point b) { return Math.Abs(a.x - b.x) > EPS ? a.x < b.x : a.y < b.y; }
        public static bool operator >(Point a, Point b) { return Math.Abs(a.x - b.x) > EPS ? a.x > b.x : a.y > b.y; }
        public static bool operator ==(Point a, Point b) { return Math.Abs(a.x - b.x) < EPS && Math.Abs(a.y - b.y) < EPS; }
        public static bool operator !=(Point a, Point b) { return Math.Abs(a.x - b.x) >= EPS || Math.Abs(a.y - b.y) >= EPS; }

        public int CompareTo(object obj)
        {
            var other = (Point)obj;
            if (obj == null) return -1;

            ComparerX compX = new ComparerX();
            return compX.Compare(this, other);
        }

        public override bool Equals(object obj)
        {
            var other = (Point)obj;
            return Math.Abs(x - other.x) < EPS && Math.Abs(y - other.y) < EPS;
        }

        public override int GetHashCode()
        {
            return x.GetHashCode() ^ y.GetHashCode();
        }

        public override string ToString()
        {
            return string.Format("{0:f10} {1:f10}", x, y);
        }
    }

    class ComparerX : IComparer<Point>
    {
        static readonly double EPS = 1E-10;

        public int Compare(Point a, Point b)
        {
            if (a.x - b.x < -EPS) return -1;
            if (a.x - b.x > EPS) return 1;
            if (a.y - b.y < -EPS) return -1;
            if (a.y - b.y > EPS) return 1;
            return 0;
        }
    }

    class ComparerY : IComparer<Point>
    {
        static readonly double EPS = 1E-10;

        public int Compare(Point a, Point b)
        {
            if (a.y - b.y < -EPS) return -1;
            if (a.y - b.y > EPS) return 1;
            if (a.x - b.x < -EPS) return -1;
            if (a.x - b.x > EPS) return 1;
            return 0;
        }
    }

    struct Segment
    {
        internal Point p1, p2;

        public Segment(Point p1, Point p2)
        {
            this.p1 = p1;
            this.p2 = p2;
        }
    }

    struct Circle
    {
        internal Point p;
        internal double r;

        public Circle(Point p, double r)
        {
            this.p = p;
            this.r = r;
        }
    }
}