1. 程式人生 > >湖南省第六屆大學生計算機程式設計競賽I

湖南省第六屆大學生計算機程式設計競賽I

I - 射擊遊戲

 

A和B在玩一個射擊遊戲,戰場由若干單位正方形積木組成。積木佔據了連續的若干列,且圖形周長等於它最小包圍矩形的周長。下圖(a)是一個合法的戰場,但(b)和(c)都不是:(b)中有空列;(c)的圖形周長為14,而最小包圍矩形(用虛線畫出)的周長為12。受重力影響,每個積木的正下方要麼是地面,要麼是另一個積木。為了讓戰場看上去錯落有致、玩著更刺激,它不能恰好是一個矩形(即:不能每列積木都一樣高)。

遊戲規則如下:

1、 A和B輪流射擊,A先射擊。

2、 每次射擊時,首先選擇一行(該行必須至少有一個積木),以及“左”和“右”中的一個方向,然後往這個方向開火。子彈的威力為1~3的均勻隨機整數(即:威力為1、2、3的概率各為1/3),表示子彈能打掉的積木個數,被打掉的積木將直接從戰場中消失。如果該行的積木個數小於威力值,則子彈將在打掉該行所有積木後消失。例如,若選擇往右射擊從下往上數第3行,且威力為2,且這一行一共有4個積木,則最左邊的兩個積木將被打掉。注意:這兩個積木可以不連續。

3、 每次射擊完成後,懸空的積木垂直往下落。所有積木不再下落後,下一位選手才能開始射擊。

4、 誰打掉了最後一個積木,誰就獲勝。

假定開局是,根據規則1,A先開火。射擊後,B可能面臨的後續局面中的其中三個如下表:

行編號(從下往上數)

子彈前進方向

威力(隨機值)

剛射擊後

積木穩定後

2

從右往左

1

(同左圖)

1

從右往左

2

1

從左往右

3

假定A和B都足夠聰明,採取讓自己獲勝概率儘量高的策略,你的任務是計算出A獲勝的概率。

Input輸入檔案最多包含25組測試資料,每個資料僅包含兩行,第一行是整數n(1<=n<=6),即積木的列數。第二行包含n個正整數h1, h2,..., hn(1<=hi<=6),表示從左往右數第i列的高度。積木的排列方式保證符合題目描述(即:圖形周長等於它最小包圍矩形的周長,且各列的高度不全相同)。n=0表示輸入結束,你的程式不應當處理這一行。Output對於每組資料,輸出僅一行,即A獲勝的概率,四捨五入保留六位小數。Sample Input
3
2 1 1
0
Sample Output
0.555556
Hint
程式碼:
#include<iostream>
#include<cstdio>
using namespace std;
#define X(A,B) (A[B[0]][B[1]][B[2]][B[3]][B[4]][B[5]])
double cache[7][7][7][7][7][7];//概率
bool vis[7][7][7][7][7][7];//統計
double win(int h[6])
{
    if(X(vis,h))
    return X(cache,h);
    X(vis,h)=true;
    X(cache,h)=0.0;
    int  mx=0;
    for(int i=0;i<6;i++)
        mx=max(mx,h[i]);//mx為最高列
    int i=0,hh[6];
    for(int j=0;j<mx;j++)
    {
        for(int d=0;d<2;d++)
        {
            i=5*d;
            double loss=0;
            for(int p=1;p<=3;p++)
            {
                for(int k=0;k<6;k++)
                    hh[k]=h[k];
                int pp=p;
                int k=i;
                while(pp)
                {
                if(k<0||k>5)
                    break;
                if(hh[k]>j)
                hh[k]--,pp--;
                k+=1-2*d;
                }
                loss+=win(hh);
            }
        loss=(1-loss/3.0);
        if(loss>X(cache,h))
        X(cache,h)=loss;
      }
  }
  return X(cache,h);
}
int main()
{ int n;
  while(scanf("%d",&n)==1&&n)
  {
    int h[6]={0};
    for(int i=0;i<n;i++)
        scanf("%d",&h[i]);
    printf("%.6lf\n",win(h));
  }
  return 0;
}