NOI 2005 聰聰與可可

首先要求出每對點之間的最短路徑(All Pairs Shortest Path,APSP),需要記錄的是path[i][j],表示在i點時,通向j的最短路徑上比i更接近j的一個點。

然後動態規劃,狀態 F[i][j] 表示貓在i,老鼠在j時,貓追上老鼠的步數的數學期望。Degree(i)爲點i的度。

狀態轉移方程

F[i][j]=sigma{ F[i'][j'] / ( Degree(j) + 1 ) } + 1

最終結果

F[C][M]

/* 
 * Problem: NOI2005 cchkk
 * Author: Guo Jiabao
 * Time: 2009.6.1 17:30
 * State: Solved
 * Memo: 動態規劃 期望計算
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXN=1001;
struct edge
{
    edge *next;
    int t;
}*V[MAXN],ES[MAXN*2];
int N,M,X,Y,EC;
int dist[MAXN],path[MAXN][MAXN],deg[MAXN],Q[MAXN];
double F[MAXN][MAXN];
bool flag[MAXN];
inline void addedge(int a,int b)
{
    ES[++EC].next = V[a];
    V[a]=ES+EC; V[a]->t=b;
    deg[a]++;
}
void init()
{
    int i,j,a,b;
    freopen("cchkk.in","r",stdin);
    freopen("cchkk.out","w",stdout);
    scanf("%d%d%d%d",&N,&M,&X,&Y);
    for (i=1;i<=M;i++)
    {
        scanf("%d%d",&a,&b);
        addedge(a,b);
        addedge(b,a);
    }
    for (i=1;i<=N;i++)
    {
        for (j=1;j<=N;j++)
            F[i][j]=-1;
        F[i][i]=0;
    }
}
void APSP()
{
    int i,j,k,head,tail;
    for (k=1;k<=N;k++)
    {
        memset(dist,-1,sizeof(dist));
        dist[k]=0;
        path[k][k]=k;
        for (Q[head=tail=0]=k;head<=tail;)
        {
            i=Q[head++];
            for (edge *e=V[i];e && (j=e->t);e=e->next)
            {
                if (dist[j] == -1)
                {
                    dist[j] = dist[i] + 1;
                    path[j][k] = i;
                    Q[++tail]=j;
                }
                else if (dist[j] == dist[i] + 1 && i < path[j][k])
                    path[j][k] = i;
            }
        }
    }
}
double dp(int i,int j)
{
    if (F[i][j]==-1)
    {
        double rs=0;
        int x = path[ path[i][j] ][j];
        rs = dp(x,j) + 1;
        if (x!=j)
        {
            for (edge *e=V[j];e;e=e->next)
                rs += dp(x,e->t) + 1;
            rs /= deg[j] + 1;
        }
        F[i][j]=rs;
    }
    return F[i][j];
}

int main()
{
    init();
    APSP();
    printf("%.3lfn",dp(X,Y));
    return 0;
}
<h2><span class="mw-headline">聰聰與可可 </span></h2>

【問題描述】

在一個魔法森林裏,住着一隻聰明的小貓聰聰和一隻可愛的小老鼠可可。雖然灰姑娘非常喜歡她們倆,但是,聰聰終究是一隻貓,而可可終究是一隻老鼠,同樣不變的是,聰聰成天想着要吃掉可可。

一天,聰聰意外得到了一臺非常有用的機器,據說是叫GPS,對可可能準確的定位。有了這臺機器,聰聰要吃可可就易如反掌了。於是,聰聰準備 馬上出發,去找可可。而可憐的可可還不知道大難即將臨頭,仍在森林裏無憂無慮的玩耍。小兔子乖乖聽到這件事,馬上向灰姑娘報告。灰姑娘決定儘快阻止聰聰, 拯救可可,可她不知道還有沒有足夠的時間。

整個森林可以認爲是一個無向圖,圖中有N個美麗的景點,景點從1至N編號。小動物們都只在景點休息、玩耍。在景點之間有一些路連接。

當聰聰得到GPS時,可可正在景點M(M≤N)處。以後的每個時間單位,可可都會選擇去相鄰的景點(可能有多個)中的一個或停留在原景點不 動。而去這些地方所發生的概率是相等的。假設有P個景點與景點M相鄰,它們分別是景點R、景點S,……景點Q,在時刻T可可處在景點M,則在(T+1)時 刻,可可有1/(P+1)的可能在景點R,有1/(P+1)的可能在景點S,……,有1/(P+1)的可能在景點Q,還有1/(P+1)的可能停在景點 M。

我們知道,聰聰是很聰明的,所以,當她在景點C時,她會選一個更靠近可可的景點,如果這樣的景點有多個,她會選一個標號最小的景點。由於聰聰太想吃掉可可了,如果走完第一步以後仍然沒吃到可可,她還可以在本段時間內再向可可走近一步。

在每個時間單位,假設聰聰先走,可可後走。在某一時刻,若聰聰和可可位於同一個景點,則可憐的可可就被吃掉了。灰姑娘想知道,平均情況下,聰聰幾步就可能吃到可可。而你需要幫助灰姑娘儘快的找到答案。

【輸入文件】
  • 從文件中讀入數據。
  • 數據的第1行爲兩個整數N和E,以空格分隔,分別表示森林中的景點數和連接相鄰景點的路的條數。
  • 第2行包含兩個整數C和M,以空格分隔,分別表示初始時聰聰和可可所在的景點的編號。
  • 接下來E行,每行兩個整數,第i+2行的兩個整數Ai和Bi表示景點Ai和景點Bi之間有一條路。
  • 所有的路都是無向的,即:如果能從A走到B,就可以從B走到A。
  • 輸入保證任何兩個景點之間不會有多於一條路直接相連,且聰聰和可可之間必有路直接或間接的相連。

    【輸出文件】

  • 輸出到文件中。

  • 輸出1個實數,四捨五入保留三位小數,表示平均多少個時間單位後聰聰會把可可吃掉。

    【樣例輸入1】

    4 3
      1 4
      1 2
      2 3
      3 4
    【樣例輸出1】
    1.500
    【樣例說明1】

    開始時,聰聰和可可分別在景點1和景點4。

    第一個時刻,聰聰先走,她向更靠近可可(景點4)的景點走動,走到景點2,然後走到景點3;假定忽略走路所花時間。

    可可後走,有兩種可能:

    第一種是走到景點3,這樣聰聰和可可到達同一個景點,可可被吃掉,步數爲1,概率爲 0.5。 第二種是停在景點4,不被吃掉。概率爲 0.5。

    到第二個時刻,聰聰向更靠近可可(景點4)的景點走動,只需要走一步即和可可在同一景點。因此這種情況下聰聰會在兩步吃掉可可。

    所以平均的步數是1 0.5+2 0.5=1.5步。

    【樣例輸入2】

    9 9
      9 3
      1 2
      2 3
      3 4
      4 5
      3 6
      4 6
      4 7
      7 8
      8 9
    【樣例輸出2】
    2.167
    【樣例說明2】

    森林如下圖所示:

    Image:Cchkk.gif

    【數據範圍】

  • 對於所有的數據,1≤N,E≤1000。

  • 對於50%的數據,1≤N≤50。

相關日誌