zoukankan      html  css  js  c++  java
  • 2018多校第九场1004(HDU 6415) DP

    本以为是个找规律的题一直没找出来。。。

    题目:给你一个n*m的矩阵和1-n*m个数,问有多少种情况满足纳什均衡的点只有一个。纳什均衡点是指这个元素在所在行和所在列都是最大的。

    思路:吉老师直播的思路:(DP O(n^4)) 可以考虑从大到小的填充这个矩阵,设dp[cnt][i][j]是已经填充了cnt个数,i行可以放置数,j列可以放置数。

    有3个状态转移过程:

    1:选择在一个不是可放置行列交叉点的一个列上的某一点放置一个数,则放置之后会产生一个新的可放置行,每一列的可选择位置是n-i个,则dp[cnt+1][i+1][j]=dp[cnt][i][j]*j*(n-i);

    2:选择行上不是交叉点的一点,原理同上,dp[cnt+1][i][j+1]=dp[cnt][i][j]*i*(m-j);

    3:选择行和列的交叉点,则一共有i*j的交叉点,已经占用了cnt个,则可选择i*j-cnt+1个,dp[cnt+1][i][j]=dp[cnt][i][j]*(i*j-cnt+1);

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int dp[2][85][85];
    int n,m,mod;
    void update(int& a,long long c){
    	a=(a+c)%mod;
    }
    void solve(){
    	int Next,now=0;
    	memset(dp,0,sizeof(dp));
    	dp[0][1][1]=n*m;
    	for(int cnt=2;cnt<=n*m;cnt++){
    		Next=now^1;
    		memset(dp[Next],0,sizeof(dp[Next]));
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=m;j++){
    				if(dp[now][i][j]){
    					update(dp[Next][i+1][j],1ll*dp[now][i][j]*j*(n-i));
    					update(dp[Next][i][j+1],1ll*dp[now][i][j]*(m-j)*i);
    					update(dp[Next][i][j],1ll*dp[now][i][j]*(i*j-cnt+1));
    				}
    			}
    		now=Next;
    	}
    	printf("%d
    ",dp[now][n][m]);
    }
    int main(){
    	int T;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d%d%d",&n,&m,&mod);
    		solve();
    	}
    } 
    

      

  • 相关阅读:
    List接口之ArrayList
    锁定线程:同步方法
    锁定线程:同步块
    通过Lambda表达式实现多线程
    通过实现Runnable接口来实现多线程
    通过继承Thread类实现多线程
    super关键字的经典案例
    Merge Two Sorted Lists
    Remove Element
    Remove Duplicates from Sorted List
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/9512875.html
Copyright © 2011-2022 走看看