CEDEC AI CHALLENGE 2014 まとめ(Part3 提出コード)

提出コード

環境

実装はC#で行った。
(とくに理由は無く、topcoderで最近お世話になっている為)

言い訳

予選コード、決勝コードともに1日で仕上げたため、
ほとんど直値でコメント無しという状態。
なのですぐ見て分かるように(自分が)以下に簡単な流れを示す。

初期化処理

熱狂度:6pt A人、5/4pt B人、3pt C人
とし、ABCのパターンを生成。
(6pt :3人、5/4pt : 3人、3pt :2人ならば"332"とする)
このパターンに一致するランクパターンを設定する。

※ランクパターン
パターンはランクA〜ランクFとし、
各ランクには目標分配値、最大分配値、最小分配値を設定している。
熱狂度の高い順にソートし、高い順にランクA、ランクB...
と設定していく。

初回(平日①、休日①)

ランダムに相手を決定。平日は熱狂度の低いものを選ぶ。
休日は熱狂度の高いものを選ぶ

初回以後(平日②〜平日⑤、休日②〜休日⑤)

以下の手順で分配を決定
1. 相手の予測
 各相手のすべての女の子に対して、今までのデート履歴から
好感度の割り当てパターンをすべて洗い出す。
その中より期待度が高いものを相手の割当として考える。

2.乱数の重み付け
1で得られた予測と、初期化時に割り当てたランクより乱数の重みを決定する。

3.乱数により割当女の子を設定

(その他、ごにょごにょしているが、応急処置的な処理なのでたいした影響は無いように思う)

提出コード(C#)

using System;
using System.Collections.Generic;

namespace AI_Lovers
{
	class GameManager
	{
		public class OneTurnInfo
		{
			public int turn;	//ターン数
			public int day;
			public int[,] lovers = new int[8,4];	//各プレイヤーの平日のみの好感度
			public int[] realLovers = new int[8];	//自プレイヤーの平日と休日をあわせた好感度
			public bool[] dated = new bool[8];

			public OneTurnInfo(){					//コンストラクタ
				turn = 0;
				day = 0;
				for(int i=0; i<8; i++){
					realLovers[i] = 0;
					dated[i] = false;
					for(int j=0; j<4; j++){
						lovers[i,j] = 0;
					}
				}
			}
		};

		public class PlanningManger
		{

			public const int RANK_A = 0;
			public const int RANK_B = 1;
			public const int RANK_C = 2;
			public const int RANK_D = 3;
			public const int RANK_E = 4;
			public const int RANK_F = 5;
			public const int RANK_NUM = 6;

			public int SCORE_A = 13;
			public int SCORE_A_MAX = 20;
			public int SCORE_A_MIN = 9;

			public int SCORE_B = 9;
			public int SCORE_B_MAX = 18;
			public int SCORE_B_MIN = 6;

			public int SCORE_C = 7;
			public int SCORE_C_MAX = 9;
			public int SCORE_C_MIN = 5;

			public int SCORE_D = 5;
			public int SCORE_D_MAX = 7;
			public int SCORE_D_MIN = 3;

			public int SCORE_E = 3;
			public int SCORE_E_MAX = 5;
			public int SCORE_E_MIN = 1;

			public int SCORE_F = 3;
			public int SCORE_F_MAX = 3;
			public int SCORE_F_MIN = 0;

			public int LANK_BORDER_C = 3;
			public int LANK_BORDER_B = 5;

			public int BORDER_SCORE_A = 10; //他プレイヤーの友好度がBORDER_SCORE_A以上ならばAランクと判定
			public int BORDER_SCORE_B = 3;	//⬆️Bランクと判定

			public int[,] RankTable = new int[45,8]
			{
				{RANK_A, RANK_C, RANK_C, RANK_D, RANK_D, RANK_E, RANK_E, RANK_F},	//800
				{RANK_A, RANK_C, RANK_C, RANK_D, RANK_D, RANK_E, RANK_E, RANK_F}, 	//701
				{RANK_A, RANK_C, RANK_C, RANK_D, RANK_D, RANK_E, RANK_E, RANK_F},	//710
				{RANK_A, RANK_C, RANK_C, RANK_C, RANK_E, RANK_E, RANK_F, RANK_F},	//602
				{RANK_A, RANK_C, RANK_C, RANK_C, RANK_E, RANK_E, RANK_E, RANK_F},	//611
				{RANK_A, RANK_C, RANK_C, RANK_D, RANK_E, RANK_E, RANK_E, RANK_E},	//620
				{RANK_A, RANK_C, RANK_C, RANK_C, RANK_D, RANK_E, RANK_F, RANK_F},	//503
				{RANK_A, RANK_C, RANK_C, RANK_C, RANK_D, RANK_E, RANK_F, RANK_F},	//512
				{RANK_A, RANK_C, RANK_C, RANK_C, RANK_D, RANK_E, RANK_F, RANK_F},	//521
				{RANK_A, RANK_C, RANK_C, RANK_D, RANK_D, RANK_E, RANK_E, RANK_F},	//530
				{RANK_A, RANK_C, RANK_C, RANK_B, RANK_E, RANK_F, RANK_F, RANK_F},	//404
				{RANK_A, RANK_C, RANK_C, RANK_C, RANK_C, RANK_F, RANK_F, RANK_F},	//413
				{RANK_A, RANK_C, RANK_C, RANK_C, RANK_D, RANK_D, RANK_F, RANK_F},	//422
				{RANK_A, RANK_C, RANK_C, RANK_C, RANK_D, RANK_D, RANK_F, RANK_F},	//431
				{RANK_A, RANK_C, RANK_C, RANK_C, RANK_E, RANK_E, RANK_E, RANK_E},	//440
				{RANK_A, RANK_C, RANK_C, RANK_E, RANK_E, RANK_E, RANK_F, RANK_F},	//305
				{RANK_A, RANK_C, RANK_C, RANK_D, RANK_E, RANK_F, RANK_F, RANK_F},	//314
				{RANK_A, RANK_C, RANK_C, RANK_D, RANK_E, RANK_F, RANK_F, RANK_F},	//323
				{RANK_A, RANK_C, RANK_C, RANK_D, RANK_D, RANK_F, RANK_F, RANK_F},	//332
				{RANK_A, RANK_C, RANK_C, RANK_D, RANK_D, RANK_F, RANK_F, RANK_F},	//341
				{RANK_A, RANK_C, RANK_C, RANK_D, RANK_E, RANK_E, RANK_F, RANK_F},	//350
				{RANK_A, RANK_C, RANK_D, RANK_D, RANK_E, RANK_E, RANK_F, RANK_F},	//206
				{RANK_A, RANK_C, RANK_B, RANK_E, RANK_E, RANK_F, RANK_F, RANK_F},	//215
				{RANK_A, RANK_C, RANK_B, RANK_E, RANK_E, RANK_F, RANK_F, RANK_F},	//224
				{RANK_A, RANK_C, RANK_B, RANK_D, RANK_D, RANK_F, RANK_F, RANK_F},	//233
				{RANK_A, RANK_C, RANK_B, RANK_D, RANK_D, RANK_F, RANK_F, RANK_F},	//242
				{RANK_A, RANK_C, RANK_B, RANK_D, RANK_D, RANK_F, RANK_F, RANK_F},	//251
				{RANK_A, RANK_C, RANK_D, RANK_D, RANK_D, RANK_F, RANK_F, RANK_F},	//260
				{RANK_B, RANK_A, RANK_D, RANK_D, RANK_D, RANK_D, RANK_E, RANK_E},	//107
				{RANK_C, RANK_B, RANK_A, RANK_D, RANK_E, RANK_E, RANK_F, RANK_F},	//116
				{RANK_C, RANK_B, RANK_A, RANK_E, RANK_E, RANK_E, RANK_F, RANK_F},	//125
				{RANK_C, RANK_B, RANK_A, RANK_C, RANK_E, RANK_E, RANK_F, RANK_F},	//134
				{RANK_C, RANK_B, RANK_A, RANK_C, RANK_E, RANK_E, RANK_F, RANK_F},	//143
				{RANK_C, RANK_B, RANK_A, RANK_C, RANK_E, RANK_E, RANK_F, RANK_F},	//152
				{RANK_C, RANK_B, RANK_B, RANK_E, RANK_E, RANK_E, RANK_F, RANK_F},	//161
				{RANK_C, RANK_B, RANK_B, RANK_E, RANK_E, RANK_E, RANK_F, RANK_F},	//170
				{RANK_B, RANK_B, RANK_B, RANK_C, RANK_E, RANK_D, RANK_F, RANK_F},	//008
				{RANK_A, RANK_B, RANK_B, RANK_C, RANK_E, RANK_E, RANK_F, RANK_F},	//017
				{RANK_A, RANK_B, RANK_B, RANK_D, RANK_E, RANK_E, RANK_F, RANK_F},	//026
				{RANK_A, RANK_B, RANK_B, RANK_C, RANK_E, RANK_E, RANK_F, RANK_F},	//035
				{RANK_B, RANK_B, RANK_B, RANK_C, RANK_E, RANK_E, RANK_F, RANK_F},	//044
				{RANK_B, RANK_B, RANK_B, RANK_C, RANK_D, RANK_E, RANK_F, RANK_F},	//053
				{RANK_B, RANK_B, RANK_B, RANK_D, RANK_D, RANK_E, RANK_E, RANK_F},	//062
				{RANK_B, RANK_B, RANK_B, RANK_D, RANK_D, RANK_E, RANK_E, RANK_F},	//071
				{RANK_B, RANK_B, RANK_B, RANK_D, RANK_D, RANK_E, RANK_E, RANK_F}	//080
			};

			public int[] defRankTbl = new int[8]{
				RANK_A, RANK_A, RANK_C, RANK_C, RANK_F, RANK_F, RANK_F, RANK_F
			};

			public string[] esseDist = new string[45] {
				"800", "701", "710", "602", "611", "620", "503", "512", "521", "530", "404", "413",
				"422", "431", "440", "305", "314", "323", "332", "341", "350", "206", "215", "224", 
				"233", "242", "251", "260", "107", "116", "125", "134", "143", "152", "161", "170", 
				"008", "017", "026", "035", "044", "053", "062", "071", "080"
			};

			Dictionary<string, int> toIndexTable = new Dictionary<string, int>();
			public int[] esse = new int[8]{0,0,0,0,0,0,0,0};
			int[] sortedGirls = new int[8]{ 0, 1, 2, 3, 4, 5, 6, 7 };
			Dictionary<int, int> goalScore = new Dictionary<int, int> ();
			Dictionary<int, int> RankList = new Dictionary<int, int> ();
			public int[,] realLovers = new int[8, 4];	//運営より与えられる全員お平日友好度
			public int[] myLovers = new int[8];		//運営より与えられる自分の友好度
			public int	myScore = 0;
			public int[,] lovers50 = new int[8,4];
			public int[,] lovers30 = new int[8,4];
			public int[,] lovers40 = new int[8,4];
			public int[,] lovers60 = new int[8,4];
			int[,] PlannerW = new int[10, 5];
			int[,] PlannerH = new int[10, 2];

			//コンストラクタ
			public PlanningManger(){
				for(int i=0; i<10; i++){
					for (int j = 0; j < 5; j++) {
						PlannerW [i, j] = 0;
					}
					for (int j = 0; j < 2; j++) {
						PlannerH [i, j] = 0;
					}
				}
				for(int i=0; i<45; i++){
					toIndexTable.Add(esseDist[i], i);
				}
			}



			public void PrintPlan(){
				string tmp = "";

				for (int i = 0; i < 10; i++) {
					tmp = "";
					if (i % 2 == 0) {
						for (int j = 0; j < 5; j++) {
							tmp += PlannerW [i, j].ToString() + ",";
						}
					} else {
						for (int j = 0; j < 2; j++) {
							tmp += PlannerH [i, j].ToString() + ",";
						}
					}
					Console.WriteLine (tmp);
				}
			}

			public void PrintGoalScore(){
				for(int i=0; i<8; i++){
					string tmp = "girl" + i.ToString() + ":"+ goalScore[i].ToString();
					Console.WriteLine(tmp);
				}
			}

			public void PrintRankList(){
				for (int i = 0; i < 8; i++) {
					string t_rank = "";
					if (RankList [i] == RANK_A)
						t_rank = "A";
					else if (RankList [i] == RANK_B)
						t_rank = "B";
					else if (RankList [i] == RANK_C)
						t_rank = "C";
					else if (RankList [i] == RANK_D)
						t_rank = "D";
					else if (RankList [i] == RANK_E)
						t_rank = "E";
					else
						t_rank = "F";

					string tmp = "girl" + i.ToString() + "RANK:" + t_rank;
					Console.WriteLine(tmp);
				}
			}

			public int GetPlanWeek(int turn, int day){
				return PlannerW [turn, day];
			}

			public int GetPlanHoli(int turn, int day){
				return PlannerH [turn, day];
			}

			public void InitializePlan(){
				//初回(平日)+次のターンは各女の子に1pointずつ配分する。
				//余った2pointはAランクの女の子へ配分する。

				//自プレイヤーのランク付け

				int g_i = 0;
				int g_alpha = 0, g_beta = 0, g_gamma = 0;
				int[] tmpAry = new int[8];

				//熱狂度の高い順にソートする
				for (int i = 0; i < 8; i++) {
					tmpAry [i] = esse [i];
				}

				g_i = 8;
				while (g_i > 0) {
					int j = 1;
					while (j < g_i) {
						if (tmpAry [j - 1] > tmpAry[j]) {
							int tmp = tmpAry [j - 1];
							int tmp2 = sortedGirls [j - 1];
							tmpAry [j - 1] = tmpAry [j];
							sortedGirls [j - 1] = sortedGirls [j];
							tmpAry [j] = tmp;
							sortedGirls [j] = tmp2;
						}
						j++;
					}
					g_i--;
				}

				//分布値作成
				for(int i=0; i<8; i++){
					if (tmpAry [i] == 6) {
						g_alpha++;
					}else if(tmpAry[i] == 3){
						g_gamma++;
					}else{
						g_beta++;
					}
				}

				//キー作成
				string s_tmp = "";
				s_tmp += g_alpha.ToString ();
				s_tmp += g_beta.ToString ();
				s_tmp += g_gamma.ToString ();

				//ランク設定
				if (toIndexTable.ContainsKey (s_tmp)) {	//キーが存在いている場合
					for(int i=0,j=7; i<8; i++,j--){
						RankList.Add(sortedGirls[i], RankTable[toIndexTable[s_tmp],j]);
							}
				} else {								//キーが存在していない場合
					for (int i = 0; i < 8; i++) {
						RankList.Add (sortedGirls [i], defRankTbl [i]);
					}
				}

				//1ターン目(平日)と2ターン目(休日)の予定を設定
				//平日
				for (int i = 0, j = 0; i < 5; i++) {
					while (true) {
						if ((RankList [j] == RANK_D) || (RankList[j] == RANK_E) || (RankList[j] == RANK_F)) {
							PlannerW [0,i] = j;
							j = (j + 1) % 8;
							break;
						}
						j = (j + 1) % 8;
					}
				}
				//休日
				for (int i = 0, j = 0; i < 2; i++) {
					while (true) {
						if ((RankList [j] == RANK_A)||(RankList[j] == RANK_B)||(RankList[j] == RANK_C)) {
							PlannerH [1,i] = j;
							j = (j + 1) % 8;
							break;
						}
						j = (j + 1) % 8;
					}
				}

				//得点の算出
				for (int i = 0; i < 8; i++) {
					if (RankList [i] == RANK_A) {
						myScore += tmpAry [i];
					} else if (RankList [i] == RANK_B) {
						;
					} else {	//RANK_C
						myScore -= tmpAry [i];
					}
				}
			}

			public void SetMyLovers(int[] arr){
				myLovers = arr;
			}

			public void SetEsseArray(int[] arr){
				esse = arr;
			}

			public void SetRealLovers(int[,] ary){
				realLovers = ary;
			}

			public void SetLovers50(int[,] ary){
				lovers50 = ary;
			}

			public void SetLovers30(int[,] ary){
				lovers30 = ary;
			}

			public void SetLovers40(int[,] ary){
				lovers40 = ary;
			}

			public void SetLovers60(int[,] ary){
				lovers60 = ary;
			}

			//修正スケジューリング
			public void Reschedule(int turn){
				//定数定義
				int[] enemyScore = new int[3];

				//相手プレイヤーの得点算出
				for (int i = 0; i < 3; i++) {	//初期化
					enemyScore [i] = 0;
				}
				for (int i = 1; i < 4; i++) {	//自得点がindex=0のため、1から開始
					for (int j = 0; j < 8; j++) {
						if (lovers50 [j, i] >= BORDER_SCORE_A) {
							enemyScore [i - 1] += esse [j];
						} else if (lovers50 [j, i] >= BORDER_SCORE_B) {
							;
						} else {
							enemyScore [i - 1] -= esse [j];
						}
					}
				}

				//プランニング
				List<int> insertList = new List<int> ();
				List<int> insertRank = new List<int> ();
				List<int> insertDiff = new List<int> ();
				//1.ランク割り当て修正

				//2.友好度配分決定処理
				//Aランク or BランクK
				for (int i = 0; i < 8; i++) {
					if ((RankList [i] == RANK_A)||(RankList[i] == RANK_B)) {
						if (RankList [i] == RANK_A) {
							if (myLovers [i] > SCORE_A_MAX) {
								continue;
							}
						} else if (RankList [i] == RANK_B) {
							if (myLovers [i] > SCORE_B_MAX) {
								continue;
							}
						} else {
							;
						}
						int max = 0;
						for (int j = 1; j < 4; j++) {
							if (max < lovers60 [i, j]) {
								max = lovers60 [i, j];
							}
						}
						if (myLovers [i] <= max) {
							insertList.Add (i);
							insertRank.Add (RankList [i]);
							if ((max - myLovers [i]) < 5)
								insertDiff.Add (max - myLovers [i]);
							else
								insertDiff.Add (4);
						} else if (((RankList [i] == RANK_A) && (myLovers [i] < SCORE_A)) ||
							((RankList [i] == RANK_B) && (myLovers [i] < SCORE_B))) {
							insertList.Add (i);
							insertRank.Add (RankList [i]);
							insertDiff.Add (1);
						} else {
							;
						}

					}
				}

				//Cランク or Dランク
				for (int i = 0; i < 8; i++) {
					if ((RankList [i] == RANK_C)||(RankList[i] == RANK_D)) {
						if (RankList [i] == RANK_C) {
							if (myLovers [i] > SCORE_C_MAX) {
								continue;
							}
						} else if (RankList [i] == RANK_D) {
							if (myLovers [i] > SCORE_D_MAX) {
								continue;
							}
						} else {
							;
						}

						int max = 0;
						for (int j = 1; j < 4; j++) {
							if (max < lovers40 [i, j]) {
								max = lovers40 [i, j];
							}
						}
						if (myLovers [i] <= max) {
							insertList.Add (i);
							insertRank.Add (RankList[i]);
							if ((max - myLovers [i] < 5))
								insertDiff.Add (max - myLovers [i]);
							else
								insertDiff.Add (4);
						} else if (((RankList [i] == RANK_C) && (myLovers [i] < SCORE_C)) ||
							((RankList [i] == RANK_D) && (myLovers [i] < SCORE_D))) {
							insertList.Add (i);
							insertRank.Add (RankList [i]);
							insertDiff.Add (1);
						} else {
							;
						}

					}
				}

				//Eランク or Fランク
				for (int i = 0; i < 8; i++) {
					if ((RankList [i] == RANK_E)||(RankList[i] == RANK_F)) {
						if (RankList [i] == RANK_E) {
							if (myLovers [i] > SCORE_E_MAX) {
								continue;
							}
						} else if (RankList [i] == RANK_F) {
							if (myLovers [i] > SCORE_F_MAX) {
								continue;
							}
						} else {
							;
						}
						int min = 999;
						for (int j = 1; j < 4; j++) {
							if (min > lovers30 [i, j]) {
								min = lovers30 [i, j];
							}
						}
						if (myLovers [i] <= min) {
							insertList.Add (i);
							insertRank.Add (RankList[i]);
							if ((min - myLovers [i] < 5))
								insertDiff.Add (min - myLovers [i]);
							else
								insertDiff.Add (4);
						} else if (((RankList [i] == RANK_E) && (myLovers [i] < SCORE_E)) ||
							((RankList [i] == RANK_F) && (myLovers [i] < SCORE_F))) {
							insertList.Add (i);
							insertRank.Add (RankList [i]);
							insertDiff.Add (1);
						} else {
							;
						}
					}
				}

				//Rank修正処理
				for (int i = 0; i < 8; i++) {
					//RANK_A修正
					for (int k = 1; k < 4; k++) {
						if ((RankList [i] == RANK_A) && (lovers50 [i, k] > SCORE_A_MAX)) {
							for (int j = 0; j < 8; j++) {
								if (i != j) {
									if ((RankList [sortedGirls [j]] == RANK_B) || (RankList [sortedGirls [j]] == RANK_C)) {
										RankList [sortedGirls [j]] = RANK_A;
										RankList [i] = RANK_E;
									}
								}
							}
						}
					}
						
					//RANk_B修正
					for (int k = 1; k < 4; k++) {
						if ((RankList [i] == RANK_B) && (lovers50 [i, k] > SCORE_B_MAX)) {
							for (int j = 0; j < 8; j++) {
								if (i != j) {
									if ((RankList [sortedGirls [j]] == RANK_C) || (RankList [sortedGirls [j]] == RANK_D)) {
										RankList [sortedGirls [j]] = RANK_B;
										RankList [i] = RANK_E;
									}
								}
							}
						}
					}
				
					//RANK_C修正
					for (int k = 1; k < 4; k++) {
						if ((RankList [i] == RANK_C) && (lovers50 [i, k] > SCORE_C_MAX)) {
							for (int j = 0; j < 8; j++) {
								if (i != j) {
									if ((RankList [sortedGirls [j]] == RANK_D) || (RankList [sortedGirls [j]] == RANK_E)) {
										RankList [sortedGirls [j]] = RANK_C;
										RankList [i] = RANK_E;
									}
								}
							}
						}
					}
					//その他ランク修正無し
				}


				//予定の決定
				Random rnd = new Random ();
				List<int> girlList = new List<int> ();
				List<int> sortList = new List<int> ();

				for (int i = 0; i < insertList.Count; i++) {
					int girl = insertList [i];
					int rank = insertRank [i];
					int diff = insertDiff [i];
					for (int j = 0; j < (diff + 1); j++) {
						int rndPlan = rnd.Next (300);
						if (((turn % 2) != 0) && (diff >= 2)) { //休日
							//休日の場合、差分が大きいものの確率をあげる
							rndPlan = (int)(rndPlan / 1.3);
						}

						//補正
						if (rank == RANK_A) {
							rndPlan = (int)(rndPlan / 1.8);
						}

						if (rank == RANK_B) {
							rndPlan = (int)(rndPlan / 1.7);
						}

						if (rank == RANK_C) {
							rndPlan = (int)(rndPlan / 1.5);
						}

						if (rank == RANK_D) {
							rndPlan = (int)(rndPlan / 1.5);
						}

						if (rank == RANK_E) {
							rndPlan = (int)(rndPlan / 1.4);
						}

						if (rank == RANK_F) {
							rndPlan = (int)(rndPlan / 1.2);
						}

						girlList.Add (girl);
						sortList.Add (rndPlan);
					}
				}

				//ソート(バブルソート(昇順))
				int g_l = girlList.Count;
				while (g_l > 0) {
					int j = 1;
					while (j < g_l) {
						if (sortList [j - 1] > sortList [j]) {
							int tmp = sortList [j - 1];
							sortList [j - 1] = sortList [j];
							sortList [j] = tmp;
						
							tmp = girlList [j - 1];
							girlList [j - 1] = girlList [j];
							girlList [j] = tmp;
						}
						j++;
					}
					g_l--;
				}

				if ((turn % 2) == 0) {	//平日
					for (int i = 0; i < 5; i++) {
						if (girlList.Count > 0) {
							PlannerW [turn, i] = girlList [0];
							girlList.RemoveAt (0);
						} else {
							int rndPlan = rnd.Next (8);
							PlannerW [turn, i] = rndPlan;
						}
					}
				} else {
					for (int i = 0; i < 2; i++) {//休日
						if (girlList.Count > 0) {
							PlannerH [turn, i] = girlList [0];
							girlList.RemoveAt (0);
						} else {
							int rndPlan = rnd.Next (8);
							PlannerH [turn, i] = rndPlan;
						}
					}
				}
			}
		}

		public class EstimationManager
		{
			public class GirlsEstimate
			{
				public Queue<int> estimateQueue = new Queue<int>();
				public int datedNum;
				public int medianScore;
				public int median50;
				public int median40;
				public int median30;
				public int median60;

				public GirlsEstimate(){
					datedNum = 0;
					medianScore = 0;
					median50 = 0;
					median40 = 0;
					median30 = 0;
					median60 = 0;
				}
			}
			public bool B_NOT_DATED = false;
			public bool B_DATED = true;

			public GirlsEstimate[,] girlsEstList = new GirlsEstimate[8,4];	//index:0 Ave index:1 player1 Ave... 
			public bool[] dummyDated = new bool[8];
			public int[,] dummyLovers = new int[8, 4];


			public EstimationManager(){
				for (int i = 0; i < 8; i++) {
					dummyDated[i] = false;
					for (int j = 0; j < 4; j++) {
						girlsEstList [i,j] = new GirlsEstimate ();
						dummyLovers [i, j] = 0;
					}
				}
			}

			public void SetDated(bool[] arry){
				dummyDated = arry;
			}

			public void SetLovers(int[,] arry){
				dummyLovers = arry;
			}

			public void EstimationGirls(){
				for (int i = 0; i < 8; i++) {
					//デート回数更新
					if (dummyDated [i] == B_DATED) {
						for (int j = 0; j < 4; j++) {
							girlsEstList [i, j].datedNum++;
						}
					}
					//キューの破棄
					for (int j = 0; j < 4; j++) {
						girlsEstList [i, j].estimateQueue.Clear ();
					}

					//RealLoversをセット
					for (int j = 1; j < 4; j++) {
						girlsEstList [i, 0].estimateQueue.Enqueue (dummyLovers [i, j]);
						girlsEstList [i, j].estimateQueue.Enqueue (dummyLovers [i, j]);
					}

					//休日デート回数分予測値作成
					for (int m = 0; m < 4; m++) {
						for (int j = 0; j < girlsEstList [i, m].datedNum; j++) {
							int stockCount = girlsEstList [i, m].estimateQueue.Count;
							for (int k = 0; k < stockCount; k++) {
								int target = girlsEstList [i, m].estimateQueue.Dequeue ();
								//デート無し(ターゲットプレイヤー)
								girlsEstList [i, m].estimateQueue.Enqueue (target);
								//デート一日あり
								girlsEstList [i, m].estimateQueue.Enqueue (target + 2);
								//デート二日あり
								girlsEstList [i, m].estimateQueue.Enqueue (target + 4);
							}
						}
					}

					//Array構造へコピー
					for (int j = 0; j < 4; j++) {
						int[] tmpArray = new int[girlsEstList [i,j].estimateQueue.Count];
						girlsEstList [i,j].estimateQueue.CopyTo (tmpArray, 0);
						Array.Sort (tmpArray);
						int dg = tmpArray.Length;
						int dg_50 = (int)(dg / 2);
						int dg_40 = (int)((dg * 40) / 100);
						int dg_30 = (int)((dg * 30) / 100);
						int dg_60 = (int)((dg * 60) / 100);
						girlsEstList [i,j].medianScore = tmpArray [dg_50];
						girlsEstList [i, j].median50 = tmpArray [dg_50];
						girlsEstList [i, j].median40 = tmpArray [dg_40];
						girlsEstList [i, j].median30 = tmpArray [dg_30];
						girlsEstList [i, j].median60 = tmpArray [dg_60];
					}
				}

			}
			public void PrintValid(){
				for (int i = 0; i < 8; i++) {
					Console.WriteLine ("Girls" + i.ToString () + ":");
					Console.WriteLine ("dateNum=" + girlsEstList [i,0].datedNum.ToString ());
					Console.WriteLine ("medianScore=" + girlsEstList [i,0].medianScore.ToString ());
					Console.WriteLine ("median40=" + girlsEstList [i,0].median40.ToString ());
					Console.WriteLine ("median30=" + girlsEstList [i,0].median30.ToString ());
				}
			}
			public int GetMedianScore(int girlID,int player){
				return girlsEstList [girlID, player].medianScore;
			}
			public int GetMedan30(int girlID,int player){
				return girlsEstList [girlID, player].median30;
			}
			public int GetMedan50(int girlID,int player){
				return girlsEstList [girlID, player].median50;
			}
			public int GetMedan40(int girlID, int player){
				return girlsEstList [girlID, player].median40;
			}
			public int GetMedan60(int girlID, int player){
				return girlsEstList [girlID, player].median60;
			}
		}

		//定数定義
		public int WEEKDAY = 0;
		public int HOLIDAY = 1;

		public int NOT_DATED = 0;
		public int DATED = 1;

		//変数定義
		public int MaxTurn;							//全ターン数
		public int Turn;							//現在のターン
		public int PlayerNum;						//プライヤーの数
		public int GirlsNum;						//女の子の数
		public int[] GirlsEnthusiam = new int[8]; 	//女の子の熱狂度
		public OneTurnInfo[] TurnInfo = new OneTurnInfo[10]; 
		public int[] todaysPlan = new int[5];
		public int[,] midiam = new int[8,4];
		public int[,] midiam30 = new int[8,4];
		public int[,] midiam40 = new int[8, 4];
		public int[,] midiam60 = new int[8, 4];
		public PlanningManger pm = new PlanningManger ();
		public EstimationManager em = new EstimationManager ();

		public GameManager(){
			MaxTurn = 0;
			Turn = 0;
			PlayerNum = 0;
			GirlsNum = 0;
			for (int i = 0; i < 8; i++) {
				GirlsEnthusiam [i] = 0;
			}
			for (int i = 0; i < 10; i++) {
				TurnInfo [i] = new OneTurnInfo ();
			}
			for (int i = 0; i < 5; i++) {
				todaysPlan[i] = 0;
			}
		}
			
		public void OutReady(){
			Console.Write("READY");
		}

		public void InitReadData(){
			//Line1
			string inputData = Console.ReadLine ();
			string[] spData = inputData.Split (' ');
			MaxTurn = int.Parse(spData [0]);
			PlayerNum = int.Parse(spData [1]);
			GirlsNum = int.Parse(spData [2]);
			//Line2
			inputData = Console.ReadLine ();
			spData = inputData.Split (' ');
			for (int i = 0; i < 8; i++) {
				GirlsEnthusiam [i] = int.Parse (spData [i]);
			}

		}

		public void TurnReadData(){
			int index = 0; //TurnInfo Index
			//Line1
			string inputData = Console.ReadLine ();
			string[] spData = inputData.Split (' ');
			Turn = int.Parse (spData [0]);
			if (Turn >= 1) {
				index = Turn - 1;
			}
			if ((index > 0) && (index <= MaxTurn)) {
				TurnInfo [index].turn = Turn;
				if (spData [1].IndexOf ("W") >= 0)
					TurnInfo [index].day = WEEKDAY;
				else
					TurnInfo [index].day = HOLIDAY;

			}

			//Line2-Line8
			for (int i = 0; i < 8; i++) {
				inputData = Console.ReadLine ();
				spData = inputData.Split (' ');
				for (int j = 0; j < 4; j++) {
					TurnInfo [index].lovers [i, j] = int.Parse (spData [j]);
				}
			}

			//Line9
			inputData = Console.ReadLine ();
			spData = inputData.Split (' ');
			for (int i = 0; i < 8; i++) {
				TurnInfo [index].realLovers [i] = int.Parse (spData [i]);
			}

			//Line10
			if (TurnInfo [index].day == WEEKDAY) {
				inputData = Console.ReadLine ();
				spData = inputData.Split (' ');
				for (int i = 0; i < 8; i++) {
					if (int.Parse (spData [i]) == DATED) {
						TurnInfo [index].dated [i] = true;
					} else {
						TurnInfo [index].dated [i] = false;
					}
				}
			}

		}

		public void InitializeData(){
			pm.SetEsseArray (GirlsEnthusiam);
		}

		public void SetTurnData(){
			if (Turn > 0) {
				em.SetDated (TurnInfo [Turn - 1].dated);
				em.SetLovers (TurnInfo [Turn - 1].lovers);
			} else {
				em.SetDated (TurnInfo [0].dated);
				em.SetLovers (TurnInfo [0].lovers);
			}
		}

		public void SetSchedulingData(){
			//修正スケジューリングデータセット
			if (Turn > 0) {
				pm.SetRealLovers (TurnInfo [Turn - 1].lovers);
			} else {
				pm.SetRealLovers (TurnInfo [0].lovers);
			}
			pm.SetMyLovers (TurnInfo [Turn - 1].realLovers);

			for (int i = 0; i < 8; i++) {
				for (int j = 0; j < 4; j++) {
					midiam [i, j] = em.GetMedianScore (i, j);
					midiam30 [i, j] = em.GetMedan30 (i, j);
					midiam40 [i, j] = em.GetMedan40 (i, j);
					midiam60 [i, j] = em.GetMedan60 (i, j);
				}
			}
			pm.SetLovers50 (midiam);
			pm.SetLovers30 (midiam30);
			pm.SetLovers40 (midiam40);
			pm.SetLovers60 (midiam60);
		}

		public void PrintInitData(){
			Console.WriteLine("MaxTurn =" + MaxTurn.ToString());
			Console.WriteLine ("PlayerNum =" + PlayerNum.ToString ());
			Console.WriteLine ("GirlsNum =" + GirlsNum.ToString ());
			for (int i = 0; i < 8; i++) {
				Console.WriteLine ("Girls" + i.ToString () + " = " + GirlsEnthusiam [i].ToString ());
			}
		}

		public void PrintTurnData(int turn){
			Console.WriteLine("Turn = " + TurnInfo[turn].turn.ToString());
			Console.WriteLine ("Days(0:W,1:H) = " + TurnInfo [turn].day.ToString ());
			for (int i = 0; i < 8; i++) {
				for (int j = 0; j < 4; j++) {
					Console.WriteLine ("Girls" + i.ToString () + "ToPlayer" + j.ToString ()
					+ "Lovers = " + TurnInfo [turn].lovers [i, j].ToString ());
				}
			}
			for (int i = 0; i < 8; i++) {
				Console.WriteLine ("Girls" + i.ToString () + "RealLovers = "
				+ TurnInfo [turn].realLovers [i].ToString ());
			}

			for (int i = 0; i < 8; i++) {
				Console.WriteLine ("Girls" + i.ToString () + "Dated = "
				+ TurnInfo [turn].dated [i].ToString ());
			}
		}

		public void WritePlanWeekday(){
			if (Turn > 0) {
				for (int i = 0; i < 5; i++) {
					todaysPlan [i] = pm.GetPlanWeek (Turn - 1, i);
				}
			}

			string outString = "";
			for (int i = 0; i < 4; i++) {
				outString += todaysPlan [i].ToString() + " ";
			}
			outString += todaysPlan [4];

			Console.Write (outString);
		}

		public void WritePlanHoliday(){
			if (Turn > 0) {
				for (int i = 0; i < 2; i++) {
					todaysPlan [i] = pm.GetPlanHoli (Turn - 1, i);
				}
			}

			string outString = "";
			for (int i = 0; i < 1; i++) {
				outString += todaysPlan [i].ToString() + " ";
			}
			outString += todaysPlan [1];

			Console.Write (outString);			

		}
	}


	class MainClass
	{
		public static void Main (string[] args)
		{
			GameManager gm = new GameManager ();
			gm.OutReady (); 			// READY 出力
			gm.InitReadData (); 		//初回入力取得
			gm.InitializeData (); 		//初回データセット
			gm.pm.InitializePlan ();	//初回プラン作成

			for (int turn = 0; turn < 10; turn++) {
				gm.TurnReadData ();	//ターン初回入力
				gm.SetTurnData ();	//データセット
				gm.em.EstimationGirls ();	//予測

				if (turn > 1) {	//2ターン目以降スケジューリング修正処理を適用する
					gm.SetSchedulingData ();	//スケジューリングデータセット
					gm.pm.Reschedule (turn);	//スケジュール修正
					}

				if (turn % 2 == 0)
					gm.WritePlanWeekday ();
				else
					gm.WritePlanHoliday ();
			}
		}
	}
}

次回 part4 結果と反省