HDU 6415 Rikka with Nash Equilibrium (DP)

题目链接

要求在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;
}

猜你喜欢

转载自blog.csdn.net/NPU_SXY/article/details/82597755
今日推荐