読者です 読者をやめる 読者になる 読者になる

CEDEC AI Challenge 2014

C++ AI
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <chrono>
#include <random>

using namespace std;

const int NUM_WEEKDAY = 5;
const int NUM_HOLIDAY = 2;
const int NUM_PLAYER = 4;
const int NUM_HEROINE = 8;
const int NUM_SELF_HAND = 100;
const int NUM_ENEMY_HAND = 1000;
const int NUM_DATE = 35;

enum rank_type { highest, lowest, middle };

struct Heroine 
{
  int popularity;
  bool dated;
  int my_fav;
  int max_fav;
  int min_fav;
  int ave_fav;
  int girl_rank;
  enum rank_type rank_status;
};

struct Hand
{
  int hand[NUM_DATE];
  double rank;
};

char day_type;
int max_turn;
int turn;
int num_player;
int num_heroine;
int sim_start_day;
int weekday_girls[NUM_WEEKDAY];
int holiday_girls[NUM_HOLIDAY];
int fav_table[NUM_HEROINE][NUM_PLAYER];
int diff_fav_table[NUM_HEROINE][NUM_PLAYER];
int date_girl_table[NUM_PLAYER][NUM_DATE];
double score_table[NUM_HEROINE][NUM_PLAYER];
vector<Heroine> Heroines;
vector<Hand> Hands; 

void init();
void read_data();
void write_command();
void think_hand();

int main() 
{
  cout << "READY" << endl;
  init();
  for ( int i = 0 ; i < max_turn ; i++ ) 
    {
      read_data(); 
      //const auto start_time = chrono::system_clock::now();     
      think_hand();
      //const auto end_time = chrono::system_clock::now();
      //const auto time_span = end_time - start_time;
      //cout << chrono::duration_cast<chrono::milliseconds>(time_span).count() << endl;
      write_command();
    }
}

void init() 
{
  cin >> max_turn >> num_player >> num_heroine;
  for ( int i = 0 ; i < num_heroine ; i++ ) 
    {
      Heroine h;
      cin >> h.popularity;
      Heroines.push_back(h);
    }
  sim_start_day = -2;
}

void read_data() 
{
  int i;
  int j;
  int tmp;
  cin >> turn >> day_type;
  for ( i = 0 ; i < num_heroine ; i++ ) 
    {
      for ( j = 0; j < num_player ; j++ )
	{
	  cin >> tmp;
	  fav_table[i][j] = tmp;
	}
    }
  for ( i = 0 ; i < num_heroine ; i++ ) 
    {
      cin >> Heroines[i].my_fav;
    }
  if ( day_type == 'W' )
    {
      int d;
      for ( i = 0 ; i < num_heroine ; i++ ) 
	{
	  cin >> d;
	}
    }
}

void write_command() 
{
  int i;
  if ( day_type == 'W' )
    {
      for ( i = 0 ; i < NUM_WEEKDAY ; i++ )
	{
	  cout << weekday_girls[i];
	  if ( i < 4 )  
	    {
	      cout << " ";
	    } 
	  else 
	    {
	      cout << endl;
	    }
	}
    } 
  else
    {
      for ( i = 0 ; i < NUM_HOLIDAY ; i++ ) 
	{
	  cout << holiday_girls[i];
	  if (i < 1)
	    {
	      cout << " ";
	    } 
	  else 
	    {
	      cout << endl;
	    }
	}
    }
}

void think_hand()
{
  int i, j, k, s, t;
  struct Hand Hand;
  vector<int> vec_rank;
  int girl;
  vector<int> favs;
  double max_fav;
  double min_fav;
  int cnt_max;
  int cnt_min;
  int score[4];
  int rank[4];
  int tmp_rank;
  double ave_rank;
  double best_rank = 5;
  int best_hand_id = 0;
  int cnt = 0;
  mt19937 generator(chrono::system_clock::now().time_since_epoch().count());
  uniform_int_distribution<int> distribution(0, 7);


  Hands.clear();
  switch ( day_type )
    {
    case 'W':
      sim_start_day += 2;
      break;
    case 'H':
      sim_start_day += 5;
      break;
    }
  for ( i = 0 ; i < NUM_SELF_HAND ; ++i )
    {
      for ( j = 0 ; j < NUM_PLAYER ; ++j )
	{
	  for ( k = 0 ; k < NUM_DATE ; ++k )
	    {
	      date_girl_table[j][k] = -1;
	    }
	}
      for ( j = 0 ; j < sim_start_day ; ++j )
	{
	  Hand.hand[j] = -1;
	}
      for ( j = sim_start_day ; j < NUM_DATE ; ++j )
	{
	  date_girl_table[0][j] = distribution(generator);
	  Hand.hand[j] = date_girl_table[0][j];
	}
      vec_rank.clear();
      for ( j = 0 ; j < NUM_ENEMY_HAND ; ++j )
	{
	  for ( k = 1 ; k < NUM_PLAYER ; ++k )
	    {
	      for ( s = sim_start_day ; s < NUM_DATE ; ++s )
		{
		  date_girl_table[k][s] = distribution(generator);
		}
	    }
	  for ( k = 0 ; k < NUM_HEROINE ; ++k )
	    {
	      for ( s = 0 ; s < NUM_PLAYER ; ++s )
		{
		  diff_fav_table[k][s] = 0;
		}
	    }
	  for ( k = 0 ; k < NUM_PLAYER ; ++k )
	    {
	      for ( s = 0 ; s < 5 ; ++s )
		{
		  for ( t = 0 ; t < NUM_WEEKDAY ; ++t )
		    {
		      girl = date_girl_table[k][ (NUM_WEEKDAY + NUM_HOLIDAY) * s + t ];
		      if ( girl == -1 ) continue;
		      diff_fav_table[girl][k] += 1;
		    }
		  for ( t = 0 ; t < NUM_HOLIDAY ; ++t )
		    {
		      girl = date_girl_table[k][ (NUM_WEEKDAY + NUM_HOLIDAY) * s + NUM_WEEKDAY + t ];
		      if ( girl == -1 ) continue;
		      diff_fav_table[girl][k] += 2;
		    }
		}
	    }
	  for ( k = 0 ; k < NUM_HEROINE ; ++k )
	    {
	      for ( s = 0 ; s < NUM_PLAYER  ; ++s )
		{
		  score_table[k][s] = 0.0;
		}
	    }
	      
	  for ( k = 0 ; k < NUM_HEROINE ; ++k )
	    {
	      favs.clear();
	      for ( s = 0 ; s < NUM_PLAYER ; ++s )
		{
		  favs.push_back(fav_table[k][s] + diff_fav_table[k][s]);
		}
	      max_fav = *max_element(favs.begin(), favs.end());
	      min_fav = *min_element(favs.begin(), favs.end());
	      cnt_max = 0;
	      cnt_min = 0;
	      for ( s = 0 ; s < NUM_PLAYER ; ++s )
		{
		  if ( favs[s] == max_fav ) { cnt_max++; }
		  if ( favs[s] == min_fav ) { cnt_min++; }
		}
	      for ( s = 0 ; s < NUM_PLAYER ; ++s )
		{
		  if ( favs[s] == max_fav ) 
		    {
		      score_table[k][s] += (double)(Heroines[k].popularity) / (double)(cnt_max);
		    } 
		  if ( favs[s] == min_fav )
		    {
		      score_table[k][s] -= (double)(Heroines[k].popularity) / (double)(cnt_min);
		    }
		}
	    }
	  for ( k = 0 ; k < NUM_PLAYER ; ++k )
	    {
	      score[k] = 0;
	      for ( s = 0 ; s < NUM_HEROINE ; ++s )
		{
		  score[k] += score_table[s][k];  
		}
	    }
	  for ( k = 0 ; k < NUM_PLAYER ; ++k )
	    {
	      tmp_rank = 1;
	      for ( s = 0 ; s < NUM_PLAYER ; ++s )
		{
		  if ( k == s ) continue;
		  if ( score[k] < score[s] ) { tmp_rank++; }
		}
	      rank[k] = tmp_rank;
	    }
	          
	  vec_rank.push_back(rank[0]);
	}

      ave_rank = 0;

      for ( j = 0 ; j < NUM_ENEMY_HAND ; ++j )
	{
	  ave_rank += vec_rank[j];
	}
      ave_rank /= NUM_ENEMY_HAND;
      Hand.rank = ave_rank;
      Hands.push_back(Hand);
    }
  for ( i = 0 ; i < NUM_SELF_HAND ; ++i )
    {
      if ( Hands[i].rank < best_rank )
	{
	  best_rank = Hands[i].rank;
	  best_hand_id = i;
	}
    }
  if ( day_type == 'W' )
    {
      for ( i = 0 ; i < NUM_DATE ; ++i )
	{
	  if ( Hands[best_hand_id].hand[i] == -1 ) continue;
	  weekday_girls[cnt] = Hands[best_hand_id].hand[i];
	  cnt++;
	  if ( cnt == NUM_WEEKDAY ) break;
	}
    }
  else if ( day_type == 'H' )
    {
      for ( i = 0 ; i < NUM_DATE ; ++i )
	{
	  if ( Hands[best_hand_id].hand[i] == -1 ) continue;
	  holiday_girls[cnt] = Hands[best_hand_id].hand[i];
	  cnt++;
	  if ( cnt == NUM_HOLIDAY ) break;
	}
    }
}