题目:是说,给定n和k,有1,2,3,4,。。。。n个数,求有多少这样的排列满足两个数之间的差的绝对值要小于等于k。(n<=15,k<=n)
解析:首先我们确定,n个数是必须要选的,所以,我们给定集合S(1.....1111)代表选了n个数。我们枚举结尾数字为i,用DP(S,i)代表选定集合S,以i为结尾数字满足条件的排列有多少。。然后我们递归不断求集合上一位的个数。看注释吧。
1 #include <cstdio> 2 #include <cmath> 3 #include <cstring> 4 using namespace std; 5 int n,k; 6 long long d[1000000][20]; 7 long long dfs(long long s,int i) 8 { 9 if(s==(1<<(i-1)))//判定是否集合内只存在i了, 10 { 11 d[s][i]=1; 12 return d[s][i]; 13 } 14 if(d[s][i]>0) return d[s][i];//记忆化搜索 15 long long temp=s; 16 17 s=s-(1<<(i-1));//将当前集合内的i删去。 18 long long ans=0; 19 for(int j=1;j<=n;j++) 20 { 21 if(fabs(j-i)<=k && s&(1<<(j-1)))//判定j必须在集合内,而且,j位的元素与结尾i处的元素差的绝对值必须<=k 22 ans+=dfs(s,j); 23 } 24 return d[temp][i]=ans; 25 } 26 int main() 27 { 28 int t; 29 scanf ("%d",&t); 30 while (t--) 31 { 32 memset(d,0,sizeof (d)); 33 scanf ("%d %d",&n,&k); 34 long long s=(1<<n)-1; 35 long long ans=0; 36 for(int i=1;i<=n;i++) 37 { 38 ans+=dfs(s,i); 39 } 40 printf("%I64d\n",ans); 41 } 42 return 0; 43 }
状态压缩入门级题目,我也算入门了。。。23333
时间: 2024-11-04 01:06:22