Light OJ 1005 - Rooks(DP)

题目大意:

给你一个N和K要求确定有多少种放法,使得没有两个车在一条线上。

N*N的矩阵, 有K个棋子。

题目分析:

我是用DP来写的,关于子结构的考虑是这样的。

假设第n*n的矩阵放k个棋子那么,这个推导过程如下。

当我们们第n*n的矩阵的时候可以考虑第(n-1)*(n-1)的矩阵经过哪些变换可以变成n*n的。

如上图蓝色方格。我们加入蓝色方格之后,矩阵就会增大一圈。

1.加入我们蓝色方格不放置棋子。 dp[n-1][k]

2.加入蓝色方格放置一枚棋子,那么我们其实有三种位置可以放置:(1)右侧蓝色(2)底侧蓝色(3)有下角。

对于每一种情况我们放置方格的位置可以有 n-k, 个故: (2*(n-k) + 1) * dp[n-1][k-1]

3.放置两个棋子, 那么放置两个棋子的话肯定不能在左下角放置。故: (n-k)*(n-k)*dp[n-1][k-2]

===========================================================================================

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef unsigned long long LL;
const int INF = 1e9+7;
const int maxn = 105;
const int MOD = 9973;
LL dp[maxn][905];
void solve()
{
    for(int i=0; i<=30; i++)
        dp[i][0] = 1;

    for(int i=1; i<=30; i++)
    for(int j=1; j<=i; j++)
    {
        dp[i][j] = dp[i-1][j] + (2*(i-j)+1) * dp[i-1][j-1];
        if(j-2 >= 0)
            dp[i][j] += (i-j+1)*(i-j+1) * dp[i-1][j-2];
    }
}

int main()
{
    int T, n, k, cas = 1;
    solve();
    scanf("%d", &T);

    while(T--)
    {
        scanf("%d %d", &n, &k);
        printf("Case %d: %llu\n",cas++, dp[n][k]);
    }
    return 0;
}
时间: 2024-09-29 23:20:13

Light OJ 1005 - Rooks(DP)的相关文章

1005 - Rooks(规律)

1005 - Rooks   PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 32 MB A rook is a piece used in the game of chess which is played on a board of square grids. A rook can only move vertically or horizontally from its current positio

Light oj 1005 - Rooks (找规律)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1005 纸上画一下,找了一下规律,Ank*Cnk. 1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include <c

LightOJ - 1005 - Rooks(组合数)

链接: https://vjudge.net/problem/LightOJ-1005 题意: A rook is a piece used in the game of chess which is played on a board of square grids. A rook can only move vertically or horizontally from its current position and two rooks attack each other if one i

2014多校第七场1005 || HDU 4939 Stupid Tower Defense (DP)

题目链接 题意 :长度n单位,从头走到尾,经过每个单位长度需要花费t秒,有三种塔: 红塔 :经过该塔所在单位时,每秒会受到x点伤害. 绿塔 : 经过该塔所在单位之后的每个单位长度时每秒都会经受y点伤害. 蓝塔 : 经过该塔所在单位之后,再走每个单位长度的时候时间会变成t+z. 思路 : 官方题解 : 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define LL long long

HDU 4901(杭电多校训练#3 1005题)The Romantic Hero(DP)

题目地址:HDU 4901 这题没想到最后居然能够做出来.... 这题用了两次DP,先从前往后求一次异或的,再从后往前求一次与运算的.分别是 1:求异或的时候,定义二维数组huo[1000][1024],前者指第几位,后者是哈希的思想,若huo[x][y]=2则表示最右边的数为第x位时,异或值为y的出现了两次,需要再定义一个hash数组,来保存前面出现的所有情况,再找有多少位的时候,用hash数组中出现的所有的值与当前的第x位的数字进行异或. 2:求与的时候,定义二维数组yu[1000][102

2014多校第四场1005 || HDU 4901 The Romantic Hero (DP)

题目链接 题意 :给你一个数列,让你从中挑选一些数组成集合S,挑另外一些数组成集合T,要求是S中的每一个数在原序列中的下标要小于T中每一个数在原序列中下标.S中所有数按位异或后的值要与T中所有的数按位与的值相同,问能找出多少符合要求的组合. 思路 :比赛的时候有点没有头绪,后来二师兄想出了状态转移方程,YN又改了很多细节,最后才A的.总之是个别扭的DP..... 一开始是 _xor[i][j^a[i]] += _xor[i-1][j] :j 的下一个状态 就是异或上a[i],这个数组所代表的意思

BZOJ 1560 火星藏宝图(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1560 题意: 思路:f[i]表示到达i的最大收益.这样是 O(n^2)的.我们考虑,由于转移的条件,a^2+b^2<(a+b)^2,因此对于三个点A.B.C.若A能到B,B能到C,那么A也能到C, 但是不如经过B更好.因此,我们记录到达第j列最靠下的i即可.那么转移(x,y)时,用记录的前y列即可. struct node { int x,y,w; }; node a[N]; int

hdu 1421 搬寝室 (dp)

思路分析: dp[i][j] 表示选取到第 i 个   组成了 j 对的最优答案. 当然排序之后 选取相邻两个是更优的. if(i==j*2) dp[i][j] = dp[i-2][j-1] + w[i]-w[i-2]^2.. else if( i> j*2 ) dp[i][j] = min (dp[i-2][j-1] + ...^2   ,    dp[i-1][j]).... #include <cstdio> #include <iostream> #include &

hdoj 1087 (DP)

代码: #include<iostream>   #include<cmath>   using namespace std;  int a[1005], dp[1005];  int main()  {      int n,sum,i,j;      while( scanf("%d",&n)&&n){             for( i=0; i<n; i++){                  scanf("%