http://acm.hdu.edu.cn/showproblem.php?pid=1297
计算F(n):
一:当最后一个是男孩M时候,前面n-1个随便排出来,只要符合规则就可以,即是F(n-1);
二:当最后一个是女孩F时候,第n-1个肯定是女孩F,这时候又有两种情况:
1)前面n-2个可以按n-2个的时候的规则来,完全可以,即是F(n-2);
2)但是即使前面n-2个人不是合法的队列,加上两个女生也有可能是合法的。当第n-2是女孩而n-3是男孩的情况,可能合法,情况总数为F(n-4);
综上所述:总数F(n)=F(n-1)+F(n-2)+F(n-4);并且,F(0)=1,F(1)=1,F(2)=2,F(3)=4。
用递归做,超时
#include<iostream> using namespace std; int f(int); int main() { int n; while(cin>>n) cout<<f(n)<<endl; return 0; } int f(int n) { if(n==0||n==1) return 1; else if(n==2) return 2; else if(n==3) return 4; else return f(n-1)+f(n-2)+f(n-4); }
改用循环做,答案错误
#include <iostream> using namespace std; int main() { int i,n,a[50]; a[0]=1; a[1]=1; a[2]=2; a[3]=4; for(i=4;i<=50;i++) a[i]=a[i-1]+a[i-2]+a[i-4]; while(cin>>n) { cout<<a[n]<<endl; } return 0; }
要考虑大数据,大数相加模板为
//大数加法 string add(string s1,string s2) { int j,l,la,lb; string max,min; max=s1;min=s2; if(s1.length()<s2.length()) {max=s2;min=s1;} la=max.size();lb=min.size(); l=la-1; for(j=lb-1;j>=0;j--,l--) max[l] += min[j]-'0'; //用到加法运算符,全部按照asiic码表来,就会多加一次48,所以要减去ascii值为48的‘0’ for(j=la-1;j>=1;j--) if(max[j]>'9'){max[j]-=10;max[j-1]++;} if(max[0]>'9') {max[0]-=10;max='1'+max;} return max; }
综上可得
#include<iostream> #include<string> using namespace std; string add(string s1,string s2) { int j,l,la,lb; string max,min; max=s1;min=s2; if(s1.length()<s2.length()) {max=s2;min=s1;} la=max.size();lb=min.size(); l=la-1; for(j=lb-1;j>=0;j--,l--) max[l] += min[j]-'0'; for(j=la-1;j>=1;j--) if(max[j]>'9'){max[j]-=10;max[j-1]++;} if(max[0]>'9') {max[0]-=10;max='1'+max;} return max; } int main(){ int n,i; string a[1001]; a[0]="1"; a[1]="1"; a[2]="2"; a[3]="4"; for(i=4;i<1001;++i) a[i]=add(add(a[i-1],a[i-2]),a[i-4]); while(cin>>n) cout<<a[n]<<endl; return 0; }