Problem:
Mysterious Gems

宇宙暦 1603〜1867 年，人々はその時代のことを EDO 時代と呼ぶ．EDO とは当時最先端の宇宙航行技術，Enhanced Driving Operation のことであり、1603 年に Dr.Izy によって開発された．

あなたは宇宙冒険家であり，宇宙を飛び回って様々な惑星を冒険していた．その冒険の途中で，あなたはとても不思議な惑星を発見した．その惑星には，至るところに七色に輝く不思議な宝石が落ちていた．あなたはその惑星への降下を試みようと考えたが，重大な問題のためにそれは不可能であることがわかった．その惑星の空気には，人間が触れただけで即死してしまうような猛毒の成分が含まれていたのだ．

そこで，あなたはロボットを使って宝石を回収することを考えついた．あなたはその惑星の周回軌道にて待機する．そして，降下させたロボットを遠隔操作することによって宝石を回収するのだ．あなたは，ロボットに「移動する方向」と「移動する距離」の組からなる命令の列によってロボットを遠隔操作する．ロボットは移動経路上（到達点を含む）に宝石を見つけると，それらを全て回収する．

あなたの仕事は，ロボットが与えられた全ての命令の実行を終えたときに，全ての宝石を回収することができたかどうかを判定するプログラムを書くことである．

なお，ロボットが不思議な宝石を回収する範囲はそれほど広くない．そのため，ロボットが移動する範囲は全て 2 次元の平面で表すことができる．そして，ロボットが移動する範囲は (0,0) および (20,20) をそれぞれ左下隅および右上隅とする正方形の内部（境界線を含む）である．ロボットは常に範囲の中央，すなわち (10,10) の座標に降下する．また，全ての宝石は中央以外の格子点上にあることが保証されている．

Input

入力は複数のデータセットにより構成される．

それぞれのデータセットの先頭行には，単一の正の整数 N (1 <= N <= 20) が含まれる。これはロボットが移動可能な範囲内にある不思議な宝石の個数を表す．次の N 行には，それぞれ xi および yi (0 <= xi , yi <= 20) が含まれ，これは i 番目の不思議な宝石の落ちている座標を表す．なお，1 つの場所に複数の宝石が落ちていることはない．

次の行には単一の整数 M (1 <= M <= 30) が含まれ，これはロボットに与えた命令の個数を表す．この後の M 行にはそれぞれ dj とひとつの正の整数 lj が含まれる．これは j 番目の命令における方向および移動量を表す．ただし，方向は N，E，S，W のいずれかの文字であり，順に北，東，南，西を表す（北は y 軸の正方向，東は x 軸の正方向）．なお，ロボットが移動可能な範囲を超えるような命令は与えられないことが保証されている．

入力は N = 0 のときに終了し，これはデータセットに含まれない．

Output

それぞれのデータセットについて，ロボットが全ての宝石を収集できるときは「Yes」と，そうでないときは「No」と 1 行に出力しなさい．

Sample Input

2
10 11
11 12
2
N 2
E 1
2
10 11
11 12
2
N 2
W 1
3
0 15
5 10
5 15
5
W 10
S 10
N 20
E 10
S 10
0

Output for the Sample Input

Yes
No
No

Solution in C# (judge verdict: Accepted)

using System;

namespace Volume20_2000
{
    class Program
    {
        static void Main(string[] args)
        {
            var map = new JewelryMap();
            var robo = new MyRobot(map);

            string jewelryCount;
            while((jewelryCount = Console.ReadLine()) != "0")
            {
                for(int i = 0; i < Convert.ToInt32(jewelryCount); i++)
                {
                    var place = Console.ReadLine().Split(' ');
                    map.SetJewelry( new Position( Convert.ToInt32(place[0]), Convert.ToInt32(place[1] ) ) );
                }

                string moveCount = Console.ReadLine();
                for (int i = 0; i < Convert.ToInt32(moveCount); i++)
                {
                    var move = Console.ReadLine().Split(' ');
                    switch (move[0])
                    {
                        case "N": robo.Move(Direction.North, Convert.ToInt32(move[1])); break;
                        case "S": robo.Move(Direction.South, Convert.ToInt32(move[1])); break;
                        case "E": robo.Move(Direction.East, Convert.ToInt32(move[1])); break;
                        case "W": robo.Move(Direction.West, Convert.ToInt32(move[1])); break;
                        default: throw new Exception();
                    }
                }

                Console.WriteLine(map.Remains == 0 ? "Yes" : "No");

                map.Reset();
                robo.Reset();
            }
        }

        enum Direction
        {
            North,
            South,
            East,
            West
        }
        struct Position
        {
            public int X;
            public int Y;
            public Position(int x, int y)
            {
                X = x;
                Y = y;
            }
            public static Position operator+ (Position pos1, Position pos2)
            {
                return new Position(pos1.X + pos2.X, pos1.Y + pos2.Y);
            }
        }
        class JewelryMap
        {
            private int maxX = 21;
            private int maxY = 21;
            private bool[,] map;
            
            public int Remains
            {
                get;
                protected set;
            }
            
            public JewelryMap()
            {
                map = new bool[maxY, maxX];
            }
            public void SetJewelry(Position pos)
            {
                if (map[pos.Y, pos.X]) return;

                map[pos.Y, pos.X] = true;
                Remains++;
            }
            public bool GetJewelry(Position pos)
            {
                if (!map[pos.Y, pos.X]) return false;

                map[pos.Y, pos.X] = false;
                Remains--;

                return true;
            }
            public Position SpawnPosition()
            {
                return new Position(maxX / 2, maxY / 2);
            }
            public void Reset()
            {
                Remains = 0;
                map = new bool[maxY, maxX];
            }
        }
        class MyRobot
        {
            public Position Position
            {
                get;
                protected set;
            }
            public int Count
            {
                get;
                protected set;
            }
            protected JewelryMap Map
            {
                get;
                set;
            }

            public MyRobot(JewelryMap map)
            {
                Position = map.SpawnPosition();
                Map = map;
            }
            public void Move(Direction dir, int value)
            {
                Position vec = new Position(0,0);
                switch(dir)
                {
                    case Direction.North:   vec.Y = 1;  break;
                    case Direction.South:   vec.Y = -1; break;
                    case Direction.East:    vec.X = 1;  break;
                    case Direction.West:    vec.X = -1; break;
                }
                for(var i = 0; i < value; i++)
                {
                    Position += vec;
                    Check();
                }
            }
            protected void Check()
            {
                if(Map.GetJewelry(Position)) Count++;
            }
            public void Reset()
            {
                Position = Map.SpawnPosition();
                Count = 0;
            }
        }
    }
}