[Jxoi2012]奇怪的道路

Description
小宇从历史书上了解到一个古老的文明。这个文明在各个方面高度发达,交通方面也不例
外。考古学家已经知道,这个文明在全盛时期有n 座城市,编号为1..n。m 条道路连接在
这些城市之间,每条道路将两个城市连接起来,使得两地的居民可以方便地来往。一对城
市之间可能存在多条道路。
据史料记载,这个文明的交通网络满足两个奇怪的特征。首先,这个文明崇拜数字K,所
以对于任何一条道路,设它连接的两个城市分别为u 和v,则必定满足1 <=|u - v| <= K。此
外,任何一个城市都与恰好偶数条道路相连(0 也被认为是偶数)。不过,由于时间过于
久远,具体的交通网络我们已经无法得知了。小宇很好奇这n 个城市之间究竟有多少种可
能的连接方法,于是她向你求助。
方法数可能很大,你只需要输出方法数模1000000007 后的结果。
Input
输入共一行,为3 个整数n,m,K。
Output
输出1 个整数,表示方案数模1000000007 后的结果。
Sample Input
【输入样例1】
3 4 1
【输入样例2】
4 3 3
Sample Output
【输出样例1】
3
【输出样例2】
4
数据规模
HINT
100%的数据满足1<= n <= 30, 0 <= m <= 30, 1 <= K <= 8.
题目说明
两种可能的连接方法不同当且仅当存在一对城市,它们间的道路数在两种方法中不同。
在交通网络中,有可能存在两个城市无法互相到达。

solution:

由于k最大只有8,所以可以用状压  (最可怕的是,我考试时想到状压,看到n,m的范围,竟然放弃了正解.............)

设f[i][j][k]为  当前到了第i位  当前用了j条路  k记录从 i-k 到 i 的状态

首先从前 i-1 转移到 i ,意义:当前第i个点不连边

然后从 i 转移到 i ,意义:当前第i个点枚举与前面点相连

ans=f[n][m][0]

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 const int mod=1000000007;
 6 const int N=(1<<9)+10;
 7 int minn(int a,int b){return a<b?a:b;}
 8 int maxn(int a,int b){return a>b?a:b;}
 9 
10 int n,m,kk,hh;
11 int maxp;
12 int f[31][31][N];
13 
14 void out11()
15 {
16     printf("\n");
17     for(int i=1;i<=n;++i)
18         for(int j=0;j<=m;++j)
19           for(int k=0;k<=maxp;++k)
20             printf("i=%d j=%d k=%d f[i][j][k]=%d\n",i,j,k,f[i][j][k]);
21     printf("\n");
22 }
23 
24 int main(){
25     //freopen("1.txt","r",stdin);
26     scanf("%d%d%d",&n,&m,&kk);
27     hh=kk+1;
28     maxp=(1<<hh)-1;
29     f[1][0][0]=1;
30     for(int i=2;i<=n;++i)
31     {
32         for(int j=0;j<=m;++j)
33           for(int k=0;k<=maxp;++k)
34             if((k&(-k))!=1)
35             {
36                 f[i][j][k>>1]+=f[i-1][j][k];
37                 f[i][j][k>>1]%=mod;
38                 }
39         //这个地方必须从i-1到i转移 
40         //如果在i从i-1推过来,会重复
41         for(int v=kk;v>=1;--v)
42         {
43             if((kk-v+2)>i)
44               break;
45             for(int j=1;j<=m;++j)
46               for(int k=0;k<=maxp;++k)
47               {
48                     f[i][j][k^(1<<(v-1))^(1<<kk)]+=f[i][j-1][k];
49                     f[i][j][k^(1<<(v-1))^(1<<kk)]%=mod;
50                 }
51         }
52     }
53     
54     //out11();
55     
56     cout<<f[n][m][0];
57     //while(1);
58     return 0;
59 }
code

 

posted @ 2017-07-29 06:32  A_LEAF  阅读(178)  评论(0编辑  收藏  举报