HDU 6415(dp/記憶化搜尋)
傳送門
題面:
Nash Equilibrium is an important concept in game theory.
Rikka and Yuta are playing a simple matrix game. At the beginning of the game, Rikka shows an n×mn×m integer matrix AA. And then Yuta needs to choose an integer in [1,n][1,n], Rikka needs to choose an integer in [1,m][1,m]. Let ii be Yuta's number and jj be Rikka's number, the final score of the game is Ai,jAi,j.
In the remaining part of this statement, we use (i,j)(i,j) to denote the strategy of Yuta and Rikka.
For example, when n=m=3n=m=3 and matrix AA is
⎡⎣⎢111241131⎤⎦⎥[121143111]
If the strategy is (1,2)(1,2), the score will be 22; if the strategy is (2,2)(2,2), the score will be 44.
A pure strategy Nash equilibrium of this game is a strategy (x,y)(x,y) which satisfies neither Rikka nor Yuta can make the score higher by changing his(her) strategy unilaterally. Formally, (x,y)(x,y) is a Nash equilibrium if and only if:
{Ax,y≥Ai,y ∀i∈[1,n]Ax,y≥Ax,j ∀j∈[1,m]{Ax,y≥Ai,y ∀i∈[1,n]Ax,y≥Ax,j ∀j∈[1,m]
In the previous example, there are two pure strategy Nash equilibriums: (3,1)(3,1) and (2,2)(2,2).
To make the game more interesting, Rikka wants to construct a matrix AA for this game which satisfies the following conditions:
1. Each integer in [1,nm][1,nm] occurs exactly once in AA.
2. The game has at most one pure strategy Nash equilibriums.
Now, Rikka wants you to count the number of matrixes with size n×mn×m which satisfy the conditions.
Input
The first line contains a single integer t(1≤t≤20)t(1≤t≤20), the number of the testcases.
The first line of each testcase contains three numbers n,mn,m and K(1≤n,m≤80,1≤K≤109)K(1≤n,m≤80,1≤K≤109).
The input guarantees that there are at most 33 testcases with max(n,m)>50max(n,m)>50.
Output
For each testcase, output a single line with a single number: the answer modulo KK.
Sample Input
2
3 3 100
5 5 2333
Sample Output
64
1170
題目描述:
讓你構造一個n*m的矩陣,使得構造出的矩陣有且只有一個點,使得他是在這一行這一列是最大的,且保證這個矩陣中的值在[1,n*m]且每個數不重複。
題目分析:
因為題目中要求有且只有一個點在一行一列中最大,因此我們考慮從大到小放點,這樣就保證了整張圖中唯一的一個符合條件的點是最大的那個點n*m。
我們可以發現,在(i,j)中放第k個點,如果要滿足題目要求使得只有一個點最大,此時我們第k+1點必然只能放在第k個點所覆蓋的第i行或第j列中。第k+2個點也只能放在[k,k+1]個點所覆蓋的行和列上。
因此我們可以發現,對於每一個點,都可以具有三種不同的狀態:
(1)覆蓋一行
(2)覆蓋一列
(3)對答案無影響(放在行和列的交界處)
因此我們可以考慮使用記憶化搜尋或者dp進行解決。
我們設dp[i][j][k]為當前放了i個點,覆蓋了i行以及j列的方案數。
倘若當前的點要覆蓋一行,則有(n-i)*j種不同的方案去放,因此此狀態轉移即為:dp[i+1][j+1][k]=dp[i][j][k]*(n-i)*j;
倘若當前的點要覆蓋一列,則有(m-j)*i種不同的方案去放,因此此時的狀態轉移即為dp[i+1][j][k+1]=dp[i][j][k]*(m-j)*i;
倘若當前點要在交界處,則有(j*k-i)種不同的方案去放,因此此時的狀態轉移即為:dp[i+1][i][k]=dp[i][j][k]*(j*k-i)。
綜合上訴我們就可以用記憶化搜尋或者遞推dp用O(n^2*m^2)的複雜度求出。(相對而言dp會更快一些)
ps:我們要注意的是取模運算在運算過程中實質上是相當的慢!!請看下圖:
在這個的做法,我在dp轉移的過程中全都加了%運算,可以看到這份程式碼的效率並不算高。
但是,倘若我們將%符號壓少,最後的取模符號,我們可以發現,時間將會變成:
我們可以發現,整份程式碼的效率直接提升了不止一倍!!同理,這個現象在記憶化搜尋中反應得更加明顯。
(同一份程式碼,一份較多取模,TLE,但是當減少模數後,時間直接縮短了近2s之多)
具體原因應該跟取模符號的性質有關,具體可以參考下文:
程式碼:
dp:
#include <bits/stdc++.h>
#define maxn 85
typedef long long ll;
ll dp[maxn*maxn][maxn][maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,m;
ll mod;
scanf("%d%d%lld",&n,&m,&mod);
for(int i=1;i<=n*m;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=m;k++) dp[i][j][k]=0;
}
}
dp[1][1][1]=m*n;
for(int i=2;i<=n*m;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=m;k++){
if(j*k<i) continue;
dp[i][j][k]+=(j*k-i+1)*dp[i-1][j][k];
dp[i][j][k]+=(dp[i-1][j-1][k]*(n-j+1)*k);
dp[i][j][k]+=(dp[i-1][j][k-1]*(m-k+1)*j);
dp[i][j][k]%=mod;
}
}
}
printf("%lld\n",dp[n*m][n][m]);
}
return 0;
}
記憶化搜尋:
#include <bits/stdc++.h>
#define maxn 85
using namespace std;
typedef long long ll;
ll n,m;
ll mod;
ll dp[maxn*maxn][maxn][maxn];
ll dfs(ll num,ll i,ll j){
if(dp[num][i][j]!=-1) return dp[num][i][j];
ll tmp=0;
if(i<n) tmp=(tmp+(n-i)*j*dfs(num+1,i+1,j))%mod;
if(j<m) tmp=(tmp+(m-j)*i*dfs(num+1,i,j+1))%mod;
if(i*j>num) tmp=(tmp+(i*j-num)*dfs(num+1,i,j))%mod;
return dp[num][i][j]=tmp;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld",&n,&m,&mod);
for(int i=1;i<=n*m;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=m;k++) dp[i][j][k]=-1;
}
}
dp[n*m][n][m]=1;
ll res=n*m%mod*dfs(1,1,1)%mod;
printf("%lld\n",res);
}
}
相關文章
- 【記憶優化搜尋/dp】HDU - 6415 - 杭電多校第九場 - Rikka with Nash Equilibrium優化UI
- hdu 6415 - DP
- HDU6415(DP)
- HDU 6415 (計數dp)
- HDU 6415 Rikka with Nash Equilibrium (DP)UI
- HDU6415:Rikka with Nash Equilibrium(dp)UI
- 記憶化搜尋
- 一類適合記憶化搜尋的區間dp
- C - Digital Path 計蒜客 - 42397(dp記憶化搜尋)Git
- HDU多校第九次 6415 (dp
- HDU-6415 Rikka with Nash Equilibrium (DP/找規律)UI
- C++記憶化搜尋C++
- HDU 6415(dp/找規律-2018多校第九場1001)
- 【leetcode 1510 石子游戲】【記憶化搜尋】LeetCode
- 【dp+組合數學】hdu 2018 多校第九場 1001 Rikka with Nash Equilibrium hdu 6415UI
- hdu 6415 Rikka with Nash EquilibriumUI
- 記憶搜尋解救滑雪問題
- HDU 4620 Fruit Ninja Extreme(搜尋)UIREM
- hdu 1175 連連看 搜尋
- HDU1560,迭代加深搜尋
- hdu 2111 Saving HDU (DP)
- hdu 1728 逃離迷宮 搜尋
- 【leetcode 3149. 找出分數最低的排列】記憶化搜尋LeetCode
- WeetCode3 暴力遞迴->記憶化搜尋->動態規劃遞迴動態規劃
- [DP]HDU6415(2018多校訓練賽第九場 Problem A) Rikka with Nash Equilibrium 題解UI
- HDU1024(dp)
- 組合數的計算(利用楊輝三角/記憶化搜尋)
- ES 筆記十七:結構化搜尋筆記
- 二叉搜尋樹 [四邊形不等式優化區間dp]優化
- HDU7458-啟發式合併最佳化DP
- 【Leetcode】1340. Jump Game V 【動態規劃/記憶性搜尋】LeetCodeGAM動態規劃
- Codeforces Round #689 (Div. 2, based on Zed Code Competition)-B. Find the Spruce(DFS+記憶化搜尋)Zed
- HDU 6035 Colorful Tree(樹形DP)
- HDU 1074 Doing Homework(狀壓DP)
- 搜尋引擎優化(SEO)優化
- 2018 Multi-University Training Contest 9----hdu 6415 Rikka with Nash EquilibriumAIUI
- 折半搜尋學習筆記筆記
- HDU4652 Dice(期望dp推式子)