例题10-13 危险的组合(Critical Mass, UVa580)

欢迎访问我的Uva题解目录哦 https://blog.csdn.net/richenyunqi/article/details/81149109

题目描述

例题10-13 危险的组合(Critical Mass, UVa580)_第1张图片

题意解析

有一些装有铀(用U表示)和铅(用L表示)的盒子,数量均足够多。要求把 n ( n ≤ 30 ) n(n≤30) nn30个盒子放成一行,但至少有3个U放在一起,有多少种放法?例如,n=4, 5, 30时答案分别为3,8和974791728。

算法设计

参考《算法竞赛入门经典(第2版)》中的提示:

答案为 f ( n ) f(n) f(n)。既然有3个U放在一起,可以根据这3个U的位置分类——对,根据前面的经验,要根据“最左边的3个U”的位置分类。假定是 i 、 i + 1 和 i + 2 i、i+1和i+2 ii+1i+2这3个盒子,则前 i − 1 i-1 i1个盒子不能有3个U放在一起的情况。设n个盒子“没有3个U放在一起”的方案数为 g ( n ) = 2 n − f ( n ) g(n)=2^n-f(n) g(n)=2nf(n),则前 i − 1 i-1 i1个盒子的方案有 g ( i − 1 ) g(i-1) g(i1)种。后面的 n − i − 2 n-i-2 ni2个盒子可以随便选择,有 2 n − i − 2 2^{n-i-2} 2ni2种。根据乘法原理和加法原理, f ( n ) = ∑ i = 1 n − 2 g ( i − 1 ) 2 n − i − 2 f(n)= \sum _{i=1} ^{n-2} g(i-1) 2^{n-i-2} f(n)=i=1n2g(i1)2ni2
遗憾的是,这个推理是有瑕疵的。即使前 i − 1 i-1 i1个盒子内部不出现3个U,仍然可能和 i 、 i + 1 和 i + 2 i、i+1和i+2 ii+1i+2组成3个U。正确的方法是强制让第i-1个盒子(如果存在)放L,则前 i − 2 i-2 i2个盒子内部不能出现连续的3个U。因此 , f ( n ) = 2 n − 3 + ∑ i = 2 n − 2 g ( i − 2 ) 2 n − i − 2 f(n)=2^{n-3}+ \sum _{i=2} ^{n-2} g(i-2) 2^{n-i-2} f(n)=2n3+i=2n2g(i2)2ni2 ,边界是 f ( 0 ) = f ( 1 ) = f ( 2 ) = 0 。 g ( 0 ) = 1 , g ( 1 ) = 2 , g ( 2 ) = 4 f(0)=f(1)=f(2)=0。g(0)=1,g(1)=2,g(2)=4 f(0)=f(1)=f(2)=0g(0)=1g(1)=2g(2)=4。注意上式中的 2 n − 3 2^{n-3} 2n3对应于i=1的情况。

算法设计

#include
using namespace std;
int main(){
    vector<int>ans={0,0,0,1};
    for(int n=4;n<=30;++n){
        ans.push_back(1<<(n-3));
        for(int i=2;i<=n-2;++i)
            ans.back()+=((1<<(i-2))-ans[i-2])*(1<<(n-i-2));
    }
    int n;
    while(cin>>n&&n!=0)
        cout<<ans[n]<<endl;
    return 0;
}

你可能感兴趣的:(算法竞赛入门经典,-,Uva)