zoukankan      html  css  js  c++  java
  • hdu 1723 DP/递推

    题意:有一队人(人数 ≥ 1),开头一个人要将消息传到末尾一个人那里,规定每次最多可以向后传n个人,问共有多少种传达方式。

    这道题我刚拿到手没有想过 DP ,我觉得这样传消息其实很像 Fibonacci 所举的例子:一个人每次能够跨一或二阶台阶,问到 n 阶台阶有几种跨法。理念是一样的,只不过跨得台阶数可能会变而已。根据 Fibonacci 数列类比过来,每次最多能传 m 人,则 A [ i ] = A [ i - m ] + A [ i - m + 1 ] +  …… + A [ i - 1 ] , 表示传到第 i 人的情况可能是传到前面 1 ~ m 人后经一步传来的,而前面项不足 m 的则都是由前面所有项累加得到的。

    是的,思路并没有问题,但是我还是 WA 了好多发,于是我找了个 AC 代码把所有解的情况打表出来找不同,终于发现了当有超过一人,而最多可向后传 0 人时,即消息不能向后传的时候,是不可能传到最后的,值是 0 ,但是不能忽略如果一开始只有一人,那么他本身就是最后一人,即使 m = 0 ,即不能向后传消息了,这时队尾的人也就是他自己也还是知道这个消息的,所以值是 1 。

    至此,我的递推就圆满 AC 了。但是这道题却的确还有 DP 的做法,即每当消息传到某个人的可能情况数增加时,那么这些情况下他同样可以再将消息一步传给他后面的第 1 ~ m 个人,这样,遍历到最前面的 m 个人时每次 dp 值 ++ ,代表从开始点一步到该点的情况,而后面的则只需要传递种类数就行。

    递推代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 int a[31],M,N;
     5 
     6 int sum(int x,int y){
     7     int i,s=0;
     8     for(i=x;i<=y;i++){
     9         s+=a[i];
    10     }
    11     return s;
    12 }
    13 
    14 void fun(){
    15     a[1]=1;
    16     a[2]=1;
    17     int i;
    18     for(i=3;i<=M;i++){
    19         a[i]=sum(1,i-1);
    20     }
    21     for(i=M+1;i<=N;i++){
    22         a[i]=sum(i-M,i-1);
    23     }
    24     return;
    25 }
    26 
    27 int main(){
    28     while(scanf("%d%d",&N,&M)!=EOF&&(N!=0||M!=0)){
    29         if(M==0){
    30             if(N==1)printf("1
    ");
    31             else printf("0
    ");
    32         }
    33         else {
    34             fun();
    35             printf("%d
    ",a[N]);
    36         }
    37     }
    38     return 0;
    39 }
    View Code

    DP 代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 int a[31],M,N;
     5 
     6 int main(){
     7     while(scanf("%d%d",&N,&M)!=EOF&&(N!=0||M!=0)){
     8         int i,j;
     9         memset(a,0,sizeof(a));
    10         a[1]=1;
    11         for(i=2;i<=N;i++){
    12             if(i-1<=M){
    13                 a[i]++;
    14             }
    15             for(j=1;j<=M&&i+j<=N;j++){
    16                 a[i+j]+=a[i];
    17             }
    18         }
    19         printf("%d
    ",a[N]);
    20     }
    21     return 0;
    22 }
    View Code
  • 相关阅读:
    mongodb 聚类查询 筛选时间
    异步线程
    性能优化
    何谓引继(引继码,继承码)?了解引继同备份不同,请注意!
    apktool 无法识别 requestLegacyExternalStorage 属性导致回编失败
    Jenkins GIT_SSH组件权限导致build失败的问题。
    Linux下 Nginx-uWSGI-Django 搭建
    SSH scp使用
    Django创建app及创建数据库
    正则表达式
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4309578.html
Copyright © 2011-2022 走看看