HDU 6415 Rikka with Nash Equilibrium (DP)

nwpu_suixy發表於2018-09-10

題目連結

要求在n*m矩陣中填入1-n*m,使得存在且僅存在1個位置,這個位置的數在所在的行與列都是最大值。問有多少種方案。

易知這個位置上必然是n*m。為了滿足有且僅有一個點符合條件,我們從n*m倒著往矩陣裡面放,顯然每個數都應該放在已經存在數的行或列上。

考慮用i個數已經在j行k列上放置了數字,在放第i+1個數之後只可能覆蓋j行k列、j+1行k列、j行k+1列。這樣分別有j*k-i、k*(n-j)、(m-k)*j種方法。依此進行狀態轉移,答案即為dp[n*m][n][m]。

第一次驚險的卡到了4882ms……後面優化到了3307ms

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 82;
const int INF = 0x3f3f3f3f;

int t, n, m;
ll mod, dp[maxn*maxn][maxn][maxn];

int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d%lld", &n, &m, &mod);
        memset(dp, 0, sizeof(dp));
        dp[1][1][1] = n*m;
        for(int i = 1;i < n*m;i++)
        {
            for(int j = 1;j <= n;j++)
            {
                if(i < j) break;
                for(int k = 1;k <= m;k++)
                {
                    if(i < k) break;
                    if(!dp[i][j][k]) continue;
                    if(k < m)
                        dp[i+1][j][k+1] = (dp[i+1][j][k+1] + dp[i][j][k]*j*(m - k)) % mod;
                    if(j < n)
                        dp[i+1][j+1][k] = (dp[i+1][j+1][k] + dp[i][j][k]*(n - j)*k) % mod;
                    if(i < j*k)
                        dp[i+1][j][k] = (dp[i+1][j][k] + dp[i][j][k]*(j*k - i)) % mod;
                }
            }
        }
        printf("%lld\n", dp[n*m][n][m]);
    }
    return 0;
}

 

相關文章