zoukankan      html  css  js  c++  java
  • 10I:核电站

    总时间限制: 
    5000ms
     
    单个测试点时间限制: 
    1000ms
     
    内存限制: 
    131072kB
    描述

    一个核电站有N个放核物质的坑,坑排列在一条直线上。如果连续M个坑中放入核物质,则会发生爆炸,于是,在某些坑中可能不放核物质。

    任务:对于给定的N和M,求不发生爆炸的放置核物质的方案总数

    输入

    只一行,两个正整数N,M( 1 < N < 50,2 ≤ M ≤ 5 )

    输出

    一个正整数S,表示方案总数。

    样例输入
    4 3
    样例输出
    13
     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 int n, m;
     5 long long d[51][6];
     6 int main(){
     7     cin>>n>>m;
     8     //d(i,j)表示从1放到第i个坑,且最后i-j+1到i个坑连续放了j个炸弹的方案数
     9     //最后结果是d[n][0]+……+d[n][m-1]
    10     d[1][0] = 1; d[1][1] = 1;
    11     for(int i = 2; i <= n; i++){
    12         for(int j = 0; j < m; j++){
    13             if(j) d[i][j] = d[i-1][j-1];
    14             else{
    15                 for(int k = 0; k < m; k++)
    16                     d[i][j] += d[i-1][k];
    17             }
    18         }
    19     }
    20     long long ans = 0;
    21     for(int i = 0; i < m; i++)
    22         ans+=d[n][i];
    23     cout<<ans<<endl;
    24      return 0;
    25 }

    备注:这道题还挺有意思的!这个思路也基本算是自己想出来了,包括的状态的定义和边界条件、最终解!但还是差了一点,没能坚持想下去,没能想到分j=0和j≠0两种情况来考虑!

    我的思考过程是这样的:很容易想到,用d[i]来表示考虑前i个坑放置炸弹的方案数,但发现仅凭这个状态没有办法转移,因为还有不能连续放m个的要求。比如说考虑d[i+1]的时候,你也不知道前i个是咋放的,因此也就不能确定第i+1个坑是否能放炸弹。

    然后我就想到,再加一个维度来记录,最后几个坑位连续放了j个炸弹这种情况,也就是说

    d(i,j)表示从1放到第i个坑,且最后i-j+1到i个坑连续放了j个炸弹的方案数

    这样我就可以知道第i个坑能不能放炸弹了!关键在于转移过程,我没能想到j分为=0和>0两种情况,关键还是对自己的思考不自信。实际上,如果j>0的话,那就要求是在d[i][j-1]的基础上放,而且第i个坑一定要放炸弹,这样才是连续放了j个,因此d[i][j]=d[i-1][j-1],那么对于=0的情况才是关键,=0的话就相当于第i个坑一定不放炸弹,那么前面就无所谓了,所以是d[i-1][k],k从0到m-1的加总。

    注意答案和数组类型都要是long long!!


    一维利用容斥原理也是可以解的!关键就在于i的分类讨论。思路如下:

     1 #include<cstdio>
     2 long long  dp[55];
     3 int main()
     4 {
     5     int n,m,i;
     6     scanf("%d%d",&n,&m);
     7     dp[0]=1;
     8     for (i=1;i<=n;i++)
     9         if (i==m) dp[i]=dp[i-1]*2-1;     //减掉都放。 
    10         else
    11         if (i<m) dp[i]=dp[i-1]*2;        //随便放不会炸。 
    12         else dp[i]=dp[i-1]*2-dp[i-m-1];
    13         /*后m个固定放时前面的有dp[i-m]种放法,这些放法中都不可取。
    14         但是这些放法中包含了第(i-m)放与不放两种可能,第(i-m)放的可能在(i-1)中就已排除,所以只需再排除不放的情况,即dp[i-m-1]。*/ 
    15     printf("%lld",dp[n]);
    16     return 0;
    17 }
  • 相关阅读:
    Android studio 克隆分支
    香蕉派 banana pi BPI-M3 八核开源硬件开发板
    Visual F# Power Tools 简单介绍
    win764bit系统plsqldeveloper11连接oracle11g64bit配置方法
    cocos2d-x 模态对话框的实现
    《AndroidStudio每日一贴》2.高速查看项目中近期的变更
    Android百日程序 开篇章:Intent打开网页
    Linux应用server搭建手冊—Weblogic服务域的创建与部署
    HDU 5623 KK's Number(DP)
    JAVA之堆内存和栈内存的差别
  • 原文地址:https://www.cnblogs.com/fangziyuan/p/13124524.html
Copyright © 2011-2022 走看看