ACM/ICPC 之 DP进阶(51Nod-1371(填数字))

原题链接:填数字

顺便推荐一下,偶然看到这个OJ,发现社区运营做得很赞,而且交互和编译环境都很赞(可以编译包括Python,Ruby,Js在内的脚本语言,也可以编译新标准的C/C++11,甚至包括Go和C Sharp等),虽然暂时不太火,但估计会逐渐成为国内算法界非常受欢迎的OJ社区。

主页:http://www.51nod.com/index.html



  

  本题是个题意简单的,思路复杂的DP题,说实话,光是想出这种DP就已经非常不易了,即便写出来也要考虑清楚每一种转移的公式和数值关系。

  

  原题:有n(1-200)行格子,第i(1<=i<=n)行有i个格子,每行格子是左对齐。现在要在每一个格子填入一个非负整数,最后使得每一行每一列的和都不超过2。

     请计算有多少种方案,答案比较大,请输出对100,000,007(1e8+7)取余后的结果。

     下图是n=4的时候格子的摆放。

      

 1 //务必注意理清每次状态转移方程的思路和公式
 2 //本人因为一个地方写多了个+1,结果WA了5发....
 3 //Memory:34900K Time:93Ms
 4 #include<iostream>
 5 using namespace std;
 6
 7 #define MAX 201
 8 #define MOD 100000007
 9
10 #define COL_0 (i - j - k - 1)    //和为0的列数
11 /*
12 * dp[i][j][k]
13 * i:表明当前行
14 * j:表明i行完成时有多少列为1
15 * k:表明j行完成时有多少列为2
16 * dp值表明该状态下的情况数
17 * 每次由 i-1行 -> i行 转移同j同k的状态
18 */
19 __int64 dp[MAX][MAX][MAX];
20
21 int main()
22 {
23     int n;
24     scanf("%d", &n);
25     dp[1][0][0] = dp[1][1][0] = dp[1][0][1] = 1;
26     for (__int64 i = 2; i <= n; i++)
27         for (__int64 j = 0; j <= i; j++)
28             for (__int64 k = 0; k <= i - j; k++)
29             {
30                 //最后一格为0时
31                 //-可+2
32                 if (i - j - k - 1 >= 1)
33                     dp[i][j][k + 1] = (dp[i][j][k + 1] + dp[i - 1][j][k] * COL_0) % MOD;
34                 //-可+1
35                 //--两个1_0-0
36                 if (i - j - k - 1 >= 2)
37                     dp[i][j + 2][k] = (dp[i][j + 2][k] + dp[i - 1][j][k] * (COL_0 * (COL_0 - 1) / 2)) % MOD;
38                 //--两个1_1-0
39                 if (j >= 1 && i - j - k - 1 >= 1)
40                     dp[i][j][k + 1] = (dp[i][j][k + 1] + dp[i - 1][j][k] * COL_0 *j) % MOD;
41                 //--两个1_1-1
42                 if (j >= 2)
43                     dp[i][j - 2][k + 2] = (dp[i][j - 2][k + 2] + dp[i - 1][j][k] * (j*(j - 1) / 2)) % MOD;
44                 //--一个1_1
45                 if (j >= 1)
46                     dp[i][j - 1][k + 1] = (dp[i][j - 1][k + 1] + dp[i - 1][j][k] * j) % MOD;
47                 //--一个1_0
48                 if (i - j - k - 1 >= 1)
49                     dp[i][j + 1][k] = (dp[i][j + 1][k] + dp[i - 1][j][k] * COL_0) % MOD;
50                 //什么都不加
51                 dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j][k]) % MOD;
52
53                 //最后一格为1时
54                 //-可+1_0
55                 if (i - j - k - 1 >= 1)
56                     dp[i][j + 2][k] = (dp[i][j + 2][k] + dp[i - 1][j][k] * COL_0) % MOD;
57                 //-可+1_1
58                 if (j >= 1)
59                     dp[i][j][k + 1] = (dp[i][j][k + 1] + dp[i - 1][j][k] * j) % MOD;
60                 //什么都不加
61                 dp[i][j + 1][k] = (dp[i][j + 1][k] + dp[i - 1][j][k]) % MOD;
62
63                 //最后一格为2时
64                 dp[i][j][k + 1] = (dp[i][j][k + 1] + dp[i - 1][j][k]) % MOD;
65             }
66
67     __int64 sum = 0;
68     for (int j = 0; j <= n; j++)
69         for (int k = 0; k <= n - j; k++)
70             sum = (sum + dp[n][j][k]) % MOD;
71     printf("%I64d\n", sum);
72
73     return 0;
74 }
时间: 2025-01-08 00:48:58

ACM/ICPC 之 DP进阶(51Nod-1371(填数字))的相关文章

2016 ACM/ICPC Asia Regional Shenyang Online 1007/HDU 5898 数位dp

odd-even number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 388    Accepted Submission(s): 212 Problem Description For a number,if the length of continuous odd digits is even and the length

2016 ACM/ICPC Asia Regional Shenyang Online 1009/HDU 5900 区间dp

QSC and Master Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 859    Accepted Submission(s): 325 Problem Description Every school has some legends, Northeastern University is the same. Enter

ACM/ICPC算法训练 之 数学很重要-浅谈“排列计数” (DP题-POJ1037)

这一题是最近在看Coursera的<算法与设计>的公开课时看到的一道较难的DP例题,之所以写下来,一方面是因为DP的状态我想了很久才想明白,所以借此记录,另一方面是看到这一题有运用到 排列计数 的方法,虽然排列计数的思路简单,但却是算法中一个数学优化的点睛之笔. Poj1037  A decorative fence 题意:有K组数据(1~100),每组数据给出总木棒数N(1~20)和一个排列数C(64位整型范围内),N个木棒长度各异,按照以下条件排列,并将所有可能结果进行字典序排序 1.每一

HDU 5000 2014 ACM/ICPC Asia Regional Anshan Online DP

Clone Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/65536K (Java/Other) Total Submission(s) : 8   Accepted Submission(s) : 5 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description After eating food from Chernobyl,

ACM/ICPC 之 数据结构-邻接表+DP+队列+拓扑排序(TshingHua OJ-旅行商TSP)

做这道题感觉异常激动,因为在下第一次接触拓扑排序啊= =,而且看了看解释,猛然发现此题可以用DP优化,然后一次A掉所有样例,整个人激动坏了,哇咔咔咔咔咔咔咔~ 咔咔~哎呀,笑岔了- -|| 旅行商(TSP) Description Shrek is a postman working in the mountain, whose routine work is sending mail to n villages. Unfortunately, road between villages is

【转】[email&#160;protected]&#183;ACM/ICPC 回忆录

转自:http://hi.baidu.com/ordeder/item/2a342a7fe7cb9e336dc37c89 2009年09月06日 星期日 21:55 初识ACM最早听说ACM/ICPC这项赛事是在大三上的算法课上张老师提到的,当时我们学校的组织参加这项活动才刚刚起步,我也没太在意,总觉得那是非常遥远的事,事实上当时我也从未相当如今我们能获得现在的成绩.真正踏入ACM/ICPC这个神奇的世界,不得不提到2004那一年我们学校的参赛队伍xmutank,正是听了pipo师兄的精彩演讲以

ACM/ICPC 之 经典动规(POJ1088-滑雪)

POJ1088-滑雪 将每个滑雪点都看作起点,从最低点开始逐个由四周递推出到达此点的最长路径的长度,由该点记下. 理论上,也可以将每一点都看作终点,由最高点开始计数,有兴趣可以试试. 1 //经典DP-由高向低海拔滑雪-求最长路 2 //Memory:372K Time:32 Ms 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 using

2014 ACM/ICPC Asia Regional Xi&#39;an Online

03 hdu5009 状态转移方程很好想,dp[i] = min(dp[j]+o[j~i]^2,dp[i]) ,o[j~i]表示从j到i颜色的种数. 普通的O(n*n)是会超时的,可以想到o[]最大为sqrt(n),问题是怎么快速找到从i开始往前2种颜色.三种.四种...o[]种的位置. 离散化之后,可以边走边记录某个数最后一个出现的位置,初始为-1,而所要求的位置就等于 if(last[a[i]]==-1) 该数没有出现过,num[i][1] = i,num[i][j+1] = num[i-1

2016 ACM/ICPC Asia Regional Shenyang Online &amp;&amp; hdoj5901 Count primes Lehmer

Count primes Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Easy question! Calculate how many primes between [1...n]! Input Each line contain one integer n(1 <= n <= 1e11).Process to end of f