codefroce 100589G (状态压缩)

  题目:是说,给定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
",ans);
41     }
42     return 0;
43 }

  状态压缩入门级题目,我也算入门了。。。23333

原文地址:https://www.cnblogs.com/bei-insomia/p/4717650.html