LightOJ1005 Rooks(DP/排列组合)

题目是在n*n的棋盘上放k个车使其不互相攻击的方案数。

首先可以明确的是n*n最多只能合法地放n个车,即每一行都指派一个列去放车。

  • dp[i][j]表示棋盘前i行总共放了j个车的方案数
  • dp[0][0]=1
  • 转移就是从第i-1行转移到第i行,对于第i行要嘛放上一个车要嘛不放,放的话有n-j-1种方法。即dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(n-j-1)。
 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 long long d[31][31];
 5 int main(){
 6     int t,n,k;
 7     scanf("%d",&t);
 8     for(int cse=1; cse<=t; ++cse){
 9         scanf("%d%d",&n,&k);
10         if(k>n){
11             printf("Case %d: 0\n",cse);
12             continue;
13         }
14         memset(d,0,sizeof(d));
15         d[0][0]=1;
16         for(int i=0; i<n; ++i){
17             for(int j=0; j<=k; ++j){
18                 d[i+1][j]+=d[i][j];
19                 if(j<k) d[i+1][j+1]+=d[i][j]*(n-j);
20             }
21         }
22         printf("Case %d: %lld\n",cse,d[n][k]);
23     }
24     return 0;
25 }

另外在别人博客看到排列组合的解法:结果就是C(n,k)*A(n,k),即从n行中选出k行来放车,然后这k行要指派的列就是从n列中选出k列的排列。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 long long C[31][31];
 5 int main(){
 6     for(int i=0; i<31; ++i) C[i][0]=1;
 7     for(int i=1; i<31; ++i){
 8         for(int j=1; j<=i; ++j) C[i][j]=C[i-1][j-1]+C[i-1][j];
 9     }
10     int t,n,k;
11     scanf("%d",&t);
12     for(int cse=1; cse<=t; ++cse){
13         scanf("%d%d",&n,&k);
14         if(k>n){
15             printf("Case %d: 0\n",cse);
16             continue;
17         }
18         long long res=C[n][k];
19         for(int i=0; i<k; ++i) res*=n-i;
20         printf("Case %d: %lld\n",cse,res);
21     }
22     return 0;
23 }
时间: 2024-10-06 00:12:21

LightOJ1005 Rooks(DP/排列组合)的相关文章

【BZOJ】4559: [JLoi2016]成绩比较 计数DP+排列组合+拉格朗日插值

[题意]n位同学(其中一位是B神),m门必修课,每门必修课的分数是[1,Ui].B神碾压了k位同学(所有课分数<=B神),且第x门课有rx-1位同学的分数高于B神,求满足条件的分数情况数.当有一位同学的一门必修课分数不同时视为两种情况不同.n,m<=100,Ui<=10^9. [算法]计数DP+排列组合+拉格朗日插值 [题解]把分数作为状态不现实,只能逐门课考虑. 设$f[i][j]$表示前i门课,有j个同学被碾压的情况数,则有: $$f[i][j]=g(i)\cdot\sum_{k=j

HDU--5396(区间dp+排列组合)

做这道题的时候,想到会不会是dp,然后发现dp可做,但是一直被自己坑到死. 枚举最后合并的那个位置,然后对于加减号的,分成的前后两个部分都有不同的组合方法, (a1+a2........) +  (b1,b2.............)         对于每个a,被加b的个数的阶乘次 ,对于每个b,被加a的个数的阶乘次 减法同理 乘法特殊一点 (a1+a2........) *  (b1,b2.............)  乘法分配率,直接将两部分的总和相乘即可 想到这些还远远没有结束,因为最

【noi 2.6_9288】&amp;【hdu 1133】Buy the Ticket(DP / 排列组合 Catalan+高精度)

题意:有m个人有一张50元的纸币,n个人有一张100元的纸币.他们要在一个原始存金为0元的售票处买一张50元的票,问一共有几种方案数. 解法:(学习了他人的推导后~) 1.Catalan数的应用7的变形.(推荐阅读:http://www.cnblogs.com/chenhuan001/p/5157133.html).P.S.不知我之前自己推出的公式“C(n,m)*C(2*m,m)/(m+1)*P(n,n)*P(m,m)”是否是正确的. (1)在不考虑m人和n人本身组内的排列时,总方案数为C(m+

【HDU】5151 Sit Sit Sit(区间DP+排列组合)

题目大意:可以查阅网站的中文翻译,就不说了,是第24场Best Coder 思路: 这道这道区间DP,我也开始觉得其实区间DP是一种应用型的思想,做这类题目一个重要的点是在于题目情景的把握,这道题的一个情景就是数学的排列组合问题. 首先应用根据小区间推出大区间的思路,我们可以先固定一个位置k,k位置是最后做的位置,那么我们要算出在这种情况下符合的方法数,假如k是头或者尾,那不用说, 此时的方法为dp[i+1][j]或者是dp[i][j-1]; 假如k是有邻居的,那我们就要考虑邻居的颜色,如果颜色

【BZOJ-1974】auction代码拍卖会 DP + 排列组合

1974: [Sdoi2010]auction 代码拍卖会 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 305  Solved: 122[Submit][Status][Discuss] Description 随着iPig在P++语言上的造诣日益提升,他形成了自己一套完整的代码库.猪王国想参加POI的童鞋们都争先恐后问iPig索要代码库.iPig不想把代码库给所有想要的小猪,只想给其中的一部分既关系好又肯出钱的小猪,于是他决定举行了一个超大型拍

hdu 5151 Sit sit sit(区间dp+排列组合)

题目链接:hdu 5151 Sit sit sit 题意: 一共有并排N个椅子, N个学生依次去坐,同时满足3个条件就不能坐下去: 1,该椅子不在最左,不在最右. 2,该椅子左右都有人坐了. 3,左右的椅子不同颜色.求最后N个人都能坐下去,有多少不同的情况. 题解: 考虑区间dp,dp[i][j] = sum(dp[i][k-1] * dp[k+1][j] * c[j - i][k - i])其中满足(v[k-1]==v[k+1]) 表示i到j区间最后来坐k位置,乘组合是因为合并这两段区间的时候

hdu5396 Expression 区间dp +排列组合

#include<stdio.h> #include<string> #include<map> #include<vector> #include<cmath> #include<stdlib.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; const int N=105; cons

HDU 4832 Chess 排列组合 DP

Chess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 351    Accepted Submission(s): 124 Problem Description 小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王"在棋盘 上的走法遵循十字

UVa 12712 &amp;&amp; UVaLive 6653 Pattern Locker (排列组合)

题意:给定 一个n * n 的宫格,就是图案解锁,然后问你在区间 [l, r] 内的所有的个数进行组合,有多少种. 析:本来以为是数位DP,后来仔细一想是排列组合,因为怎么组合都行,不用考虑实际要考虑的比如 要连13,必须经过2,这个可以不用. 所以这题就是A(n,m).剩下的就简单了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <s