Dp-劍客決鬥


劍客決鬥

時間限制:5000 ms  |  內存限制:65535 KB
難度:5
描述

在路易十三和紅衣主教黎塞留當權的時代,發生了一場決鬥。n個人站成一個圈,依次抽籤。抽中的人和他右邊的人決鬥,負者出圈。這場決鬥的最終結果關鍵取決於決鬥的順序。現書籍任意兩決鬥中誰能勝出的信息,但“A贏了B”這種關係沒有傳遞性。例如,A比B強,B比C強,C比A強。如果A和B先決鬥,C最終會贏,但如果B和C決鬥在先,則最後A會贏。顯然,他們三人中的第一場決鬥直接影響最終結果。

假設現在n個人圍成一個圈,按順序編上編號1~n。一共進行n-1場決鬥。第一場,其中一人(設i號)和他右邊的人(即i+1號,若i=n,其右邊人則爲1號)。負者被淘汰出圈外,由他旁邊的人補上他的位置。已知n個人之間的強弱關係(即任意兩個人之間輸贏關係)。如果存在一種抽籤方式使第k個人可能勝出,則我們說第k人有可能勝出,我們的任務是根據n個人的強弱關係,判斷可能勝出的人數。

輸入
第一行是一個整數N(1<=N<=20)表示測試數據的組數。
第二行是一個整數n表示決鬥的總人數。(2<=n<=500)
隨後的n行是一個n行n列的矩陣,矩陣中的第i行第j列如果爲1表示第i個人與第j個人決鬥時第i個人會勝出,爲0則表示第i個人與第j個人決鬥時第i個人會失敗。
輸出
對於每組測試數據,輸出可能勝出的人數,每組輸出佔一行
樣例輸入
1
3
0 1 0
0 0 1
1 0 0
樣例輸出
3

狀態方程:

dp[i][j]  表示i是否可以遇到j

問題轉化成了是否能在這條鏈中找到一個k,使得 i 和 k , k 和 j 均能相遇,且 i 或者 j 能打敗 k 。

狀態轉移方程是:dp[i,j] = true( 存在k∈鏈{i,j}使得meet[i,k]且meet[k,j]且(beat[i,k]或beat[j,k]) )

初始值dp[i,i+1] = true,計算順序依然是沿對角線的順序。


 
#include <stdio.h>
#include <string.h>

#define N 505

bool beat[N][N],meet[N][N];

int main()
{
    int z,n;
    scanf("%d",&z);
    while(z--)
    {
        memset(meet,false,sizeof(meet));
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&beat[i][j]);
        for(int i=0;i<n-1;i++)
            meet[i][i+1] = true;
        meet[n-1][0] = true;
        for(int d=2;d<=n;d++)
            for(int i=0;i<n;i++)
            {
                int j = i+d;
                for(int k=i+1;k<j;k++)
                {
                    if(meet[i][k%n] && meet[k%n][j%n] && (beat[i][k%n] || beat[j%n][k%n]))
                    {
                        meet[i][j%n] = true;
                        break;
                    }
                }
            }
        int ans = 0;
        for(int i=0;i<n;i++)
            if(meet[i][i])
                ++ans;
        printf("%d\n",ans);
    }
	return 0;
}
        







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章