排列问题

      在整数1,2,…,N的排列中,有些排列满足下面一个性质A:该排列中除了最后一个整数外的每一个整数后面都跟有一个与它相差为1的数字。设有N个数字,已知一部分位置上的数,求满足性质A的排列有多少个?

     

分析:假设只有一个数字, 即N=1,则满足A条件。若只有两个数字,则一定满足。若有三个数字,不论最后一个数字是什么,满足A条件的后缀序列必然是连续数字组成的集合。例如3个数字的时候,后两个数字不可能为(1,3)。根据这个属性我们设计动态规划算法。

假设

       f(s,r)表示范围在[s,s+r-1]的数字组成的满足A性质的串的数量。

      

       则                                      f(s+1,r-1)                  若r位置确定为s

                         f(s,r)=             f(s,r-1)                       若r位置确定为s+r-1

                                                f(s+1,r-1)+f(s,r-1)     若r位置没有确定

 

       以前也做过这道题,

include <stdlib.h> #include <iostream> #include <memory.h> class RankProgram { public: RankProgram() { std::cout<<“please input the testing data”<<std::endl; std::cin>>n>>p; s=new int[n+2]; g=new int* [n+2]; for(int i=0;i<=n+1;i++) { g[i]=new int[n+2]; memset(g[i],0,sizeof(int)*(n+2)); g[i][1]=1; } memset(s,0,sizeof(int)*(n+2)); int tempData; int tempP; for(int i=1;i<=p;i++) { std::cin>>tempP>>tempData; s[n-tempP+1]=tempData; } for(int i=n;i>=1;i–) { for(int j=2;j<=n-i+1;j++) { if(s[j]==i) g[i][j]=g[i+1][j-1]; else if(s[j]==(i+j-1)) g[i][j]=g[i][j-1]; else g[i][j]=g[i+1][j-1]+g[i][j-1]; } } std::cout<<g[1][n]<<std::endl; } ~RankProgram() { delete [] s; for(int i=0;i<=n+1;i++) delete [] g[i]; delete [] g; } private: int *s; int **g; int p; int n; }; int main() { RankProgram rp; }

点赞