Conqueror's battalion

Conqueror's battalion

In the whole history of mankind one can find several curious battles, like the following one in France, in 1747...

There was a fortress in Bassignac-le-Haut, a small village lying on the left bank of river Dordogne, just over the Chastang dam. From the dam up to the fortress there was a wide staircase made out of "#008DDC" marble. One day in the morning, the guard spotted a large battalion approaching the fortress, with a dreaded leader - The Conqueror.

When The Conqueror reached the fortress, he was already awaited by its commandant. As the commandant had only a small part of his soldiery available, he proposed to The Conqueror: "I see that you have many soldiers behind you, standing on the stairs. We can play a small 'game': In each round, you will divide your soldiers into two groups in an arbitrary way. Then I will decide which one of them stays and which one goes home. Each soldier that stays will then move up one stair. If at least one of your soldiers reaches the uppermost stair, you will be the winner, in the other case, you will be the loser. And your destination will be the dam down there...", added the commandant, pointing to the Chastang dam by his hand.

The Conqueror immediately liked this game, so he agreed and started to 'conquer'.

Task

Your role is The Conqueror's now. There are N stairs to the fortress (2<=N<=2000) and you have at most 1 000 000 000 soldiers. For each stair, you are given the number of soldiers standing on it, with number 1 being the uppermost stair and N the bottom one. None of your soldiers stands on stair 1 at the beginning.

For each starting position given to your program, if the position is winning (i.e. there is a strategy that enables you to win the game regardless of your opponent's moves), your program should win. Otherwise it should just play the game (and lose) correctly.

This is an interactive problem; you will play against a library as specified below. In each round, your program will describe a group of soldiers to our library. The library returns 1 or 2 specifying which group of soldiers should stay (1 means the group you described, 2 means the rest of the soldiers). In case the game ends (either because you won or there are no more soldiers in the game), the library will terminate your program correctly. Your program may not terminate in any other way.

Library interface

The library libconq provides two routines:

  • start - returns the number N and fills an array stairs with numbers of soldiers standing on the stairs (i.e. there are stairs soldiers standing on stair i)
  • step - takes an array subset (with at least N elements), describing the group of soldiers you chose, and returns 1 or 2 as described above; the group of soldiers is specified by numbers of soldiers on each stair, as in the start function
If you fail to specify a valid group of soldiers, the game will be terminated and your program will score zero points for the particular test case. Please note that also in C/C++ the stairs are numbe"#008DDC" starting from 1.

Following are the declarations of these routines in FreePascal and C/C++:

  procedure start(var N: longint; var stairs:array of longint);
  function step(subset:array of longint): longint;
  void start(int *N, int *stairs);
  int step(int *subset);

Below you can find examples of library usage in both FreePascal and C/C++; both fragments do the same - start the game and then play one round, with the chosen group containing all soldiers on randomly chosen stairs. Your real program will probably play the rounds in an infinite loop.

You are strongly encouraged to define the arrays stairs and subset in the same way as they are defined in the example below. (Note that the FreePascal library returns its answer in the first N elements of the array regardless of how you defined it, the C/C++ library returns its answer in the elements with indices 1 to N.)

 

You have to link the library to your program - by uses libconq; in FreePascal and by #include "libconq.h" in C/C++, where you have to compile your program by adding libconq.c to the compiler arguments.

An example of the game

YouLibrary
start(N,stairs)N=8, stairs=(0,1,1,0,3,3,4,0)
step((0,1,0,0,1,0,1,0))returns 2
step((0,1,0,0,0,1,0,0))returns 2
step((0,0,0,3,2,0,0,0))returns 1
step((0,0,2,0,0,0,0,0))returns 2
step((0,1,0,0,0,0,0,0))returns 2
step((0,1,0,0,0,0,0,0))no return: you won

Resources

On the web page you may find example libraries for both C/C++ and FreePascal. These libraries are different from those that will be used during testing. You may use them to make sure your library calls are correct. The example library reads the input from the file libconq.dat, containing two lines. On the first line is the number N of stairs, the second line contains N integers - the numbers of soldiers on each of the stairs 1..N.

The file libconq.dat for the example above would look like this:

  8
  0 1 1 0 3 3 4 0

 

 
 
 
libconq.h (C/C++)

  #ifndef __LIBCONQ_H
  #define __LIBCONQ_H

  #define MAX_N 2000
  #define MAX_M 1000000000

  void start(int *N, int *stairs);
  int step(int *subset);

  #endif /* __LIBCONQ_H */

 


libconq.c (C/C++)

  #include 
 
 
  #include 
 
 
  #include 
 
 
  #include 
 
 
  #include "libconq.h"

  static int game_N=0;
  static int st;

  static int lib_usage = 0;
  static char lib_txt;

  static void lib_error(int code, char *s)
  {
    FILE *f;
    f=fopen("libconq.out","w");
    fprintf(f,"%s/n",s);
    fclose(f);
    exit(code);
  }

  void start(int *N, int *stairs)
  {
    FILE *f;
    int i;

    if (lib_usage!=0)
      lib_error(1,"start() called too many times");
    lib_usage++;

    if ((f=fopen("libconq.dat","r"))==NULL)
    {
      srand(time(NULL));
      (*N)=2 + rand()%(MAX_N-2);
      stairs=0;
      for (i=2;i<=(*N);i++) stairs=rand()%(i*i);
    }
    else
    {
      fscanf(f,"%d ",N);
      for (i=1;i<=(*N);i++) fscanf(f,"%d ",&stairs);
      fclose(f);
    }

    game_N=(*N);
    for (i=1;i<=(*N);i++) st;
  }

  static int decide(int *a)
  {
    return (1+rand()%2);
  }

  int step(int *subset)
  {
    int choice,i,wrong,cnt;

    if (lib_usage==0) lib_error(1,"call start() first!");
    lib_usage++;

    /* check if a is a valid subset */
    wrong=0;
    for (i=1;i<=game_N;i++)
    {
      if ((subset)) wrong=i;
      if (wrong) break;
    }

    if (wrong!=0)
    {
      sprintf(lib_txt,"wrong number of soldiers on stair %d: %d requested, %d available",wrong,subset);
      lib_error(1,lib_txt);
    }

    /* decide */
    choice=decide(subset);

    /* choice 1: move subset one stair up, discard the rest */
    if (choice==1)
    {
      for (i=1;i<=game_N;i++) st;
      for (i=1;i<=game_N;i++) st;
    }
    else  /* choice 2: discard subset, move complement one stair up */
    {
      for (i=1;i<=game_N;i++) st;
      for (i=1;i<=game_N;i++) st;
    }

    /* check if there are any soldiers left */
    /* check if there is any soldier at position 1 */
    cnt=0;
    for (i=1;i<=game_N;i++) cnt+=(!!st);

    if (cnt==0)
    {
      sprintf(lib_txt,"You lost!");
      lib_error(0,lib_txt);
    }

    if (st)
    {
      sprintf(lib_txt,"You won!");
      lib_error(0,lib_txt);
    }

    return choice;
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值