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 }
  • 相关阅读:
    D. Babaei and Birthday Cake--- Codeforces Round #343 (Div. 2)
    Vijos P1389婚礼上的小杉
    AIM Tech Round (Div. 2) C. Graph and String
    HDU 5627Clarke and MST
    bzoj 3332 旧试题
    codeforces 842C Ilya And The Tree
    codesforces 671D Roads in Yusland
    Travelling
    codeforces 606C Sorting Railway Cars
    codeforces 651C Watchmen
  • 原文地址:https://www.cnblogs.com/fangziyuan/p/13124524.html
Copyright © 2011-2022 走看看