zoukankan      html  css  js  c++  java
  • 【DP】【芝麻开门】

    【题目来源】http://acm.buaa.edu.cn/problem/403/

    【个人体会】觉得自己弱爆了。。。当时做的时候实在不会,问了各路大神,得到的解法也不尽相同,有的至今仍感觉懵懵懂懂。当时看完题目后唯一的想法就是任意的前I个房间都必须有大于I的房间钥匙(除非是N),之后再无进展。。。也曾经想过让DP(I)表示到达不了I这个房间的方案数,当时分为两种情况考虑,一是钥匙编号全部小于I,二是有某些房间钥匙的编号大于I,但是这些房间又是到达不了的。情况二让我感觉很麻烦,于是就退缩不再继续想下去了。现在回头看来,情况二实则可以再进一步,不仅仅是不能到达I,更精确是必然也不能到达I之前的某个房间。

    【题目解析】DP(I)表示的是最远可以到达房间I的方案数,DP(I) = I^I - 最远不能到I的方案数,假设最远能到达房间J, 1<=J<I。那么J+1~I的房间可以随便放钥匙,方案数为I^(I-J)。状态转移方程为DP(I) = I^I - SUM{DP(J) * I ^ (I - J)},只有一个边界条件就是F[1]=1。

          PS:要预先处理出I^J取模的数值,不然会超时。

    【代码如下】

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 typedef long long int64;
     6 
     7 const int mod = 20121215, Maxn = 101;
     8 int N;
     9 int64 List[Maxn][Maxn], F[Maxn];
    10 
    11 int64 Dp(int i)
    12 {
    13     if (F[i]) return F[i];
    14     if (i == 1) return 1;
    15     int64 sum = List[i][i];
    16     for (int j = 1; j < i; j ++)
    17     {
    18         sum -= ((Dp(j) % mod) * List[i][i - j]) % mod;
    19         if (sum < 0) sum += mod;
    20     }
    21     F[i] = sum;
    22     return sum;
    23 }
    24 
    25 void Prework()
    26 {
    27     for (int i = 1; i < Maxn; i ++)
    28     {
    29         List[i][0] = 1;
    30         for (int j = 1; j < Maxn; j ++)
    31             List[i][j] = ((List[i][j - 1] % mod) * i) % mod;
    32     }
    33 }
    34 
    35 int main()
    36 {
    37     Prework();
    38     while (cin >> N) cout << Dp(N) << endl;
    39     return 0;
    40 }
  • 相关阅读:
    数据库高级查询
    简明python教程笔记一
    2017.12.29问题
    Windows下Python + Flask环境搭建
    ApiTestEngine框架
    接口测试框架ApiTestEngine相关
    IDEA查看JMeter源码
    IDEA安装,破解,和配置
    Uiautomator 2.0实例
    框架搭建实例
  • 原文地址:https://www.cnblogs.com/GXZC/p/2839186.html
Copyright © 2011-2022 走看看