zoukankan      html  css  js  c++  java
  • uva 12371 Guards (dp)

    题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3793

    首先发现按照规定的摆放方法一定会有圈,其中每个圈的相邻两行都有一对棋子位于同一列上

    (dp[i][j]) 表示 (i*i) 的棋盘上有 (j) 个圈的方案数,则转移的时候分增不增加圈数来讨论

    • 不增加圈数

    (i*i) 这个格子有没有守卫来讨论

    如果有,只需从前 (i-1) 行中选一行,将右侧的守卫移动到最后一列,再在最后一行的相应位置增加一个守卫即可,对应的转移方程为 (dp[i][j] += dp[i-1][j]*(i-1))

    如果没有,需要从前 (i-1) 列选择一列,将该列两个守卫移动到最后一列中同样的位置,然后在前 (i-1) 行选择一行,将左侧的守卫移动到之前选择的一列的最后一行,再加上最后一行剩余的守卫即可,对应的转移方程为 (dp[i][j] += dp[i-1][j] * (i-1) * (i-1))

    • 增加圈数

    由上面的讨论可知,还有一种情况是增加一个 (2*2) 的圈,方法是在最后一行选择两个位置作为下半部分,再在前 (i-1) 行选择一行作为上半部分,对应的转移方程为 (dp[i][j] += dp[i-2][j-1] * C_n^2 * (i-1))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 100010;
    const int maxk = 55;
    const int M = 1000000007;
    
    int T, n, k;
    int dp[maxn][maxk];
    
    int sqr(ll x){
    	x %= M;
    	return 1ll * x * x % M;
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	dp[2][1] = 1;
    	for(int i = 3 ; i <= 100000 ; ++i){
    		for(int j = 1 ; j <= 50 ; ++j){
    			dp[i][j] = 1ll * dp[i-1][j] * (i-1) % M * i % M;
    			dp[i][j] = (dp[i][j] + 1ll * dp[i-2][j-1] * (1ll * i * (i-1)/2) % M * (i-1) % M) % M;
    		}
    	}
    	
    	scanf("%d", &T);
    	for(int kase = 1 ; kase <= T ; ++kase){
    		scanf("%d%d", &n, &k);
    		printf("Case %d: %d
    ", kase, dp[n][k]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    python获取公网ip,本地ip及所在国家城市等相关信息收藏
    Tkinter的下拉列表Combobox
    pyinstaller打包pyqt文件(转)
    通过pyqt5实现俄罗斯方块游戏例子
    pygame游戏开发入门例子
    python界面Tkinter编程(tkMessageBox对话框使用)
    python tkinter-菜单栏
    python tkinter-容器、子窗体
    HUNNU--湖师大--11409--Skill
    [置顶] 博客搬迁到新地址。
  • 原文地址:https://www.cnblogs.com/tuchen/p/15113597.html
Copyright © 2011-2022 走看看