zoukankan      html  css  js  c++  java
  • bzoj3195: [Jxoi2012]奇怪的道路

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 197  Solved: 122
    [Submit][Status][Discuss]

    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.

    【题目说明】

    两种可能的连接方法不同当且仅当存在一对城市,它们间的道路数在两种方法中不同。

    在交通网络中,有可能存在两个城市无法互相到达。

    Source

                            [Submit][Status][Discuss]
    题解:
      
      可以把图中的点看成一列数,在这列数中连边,搞DP。
      用f[i][j][s][c]表示处理到第i个点,共用j条边,(i-k)~i 这些点度的奇偶性为二进制数s,当前处理的连边为 i 到 i - k + c 的方案数
      对于c < k,若连边,则可以转移到f(i, j + 1, s', k);若不连边,则可以转移到f(i, j, s, k + 1)。
      对于c = k,只有当i - k的度为偶数才可以转移到f(i + 1, j, s', 0)。
      时间复杂度O(NMK * 2^K)。

      比较难理解,具体看代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int mod=1000000007;
     4 inline int read(){
     5     int x=0,f=1;char ch=getchar();
     6     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 
     7     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     8     return x;
     9 }
    10 int N,M,K;
    11 int f[35][35][1025][9];//f[i][j][s][c]表示处理到第i个点,共用j条边,
    12                       //第三维表示(i-k)~i这些点度的奇偶性为二进制数s,0表示偶数,1表示奇数
    13                      //当前处理的连边为(i,i-k+c)的方案数。
    14 int main(){
    15     N=read(),M=read(),K=read();
    16     f[2][0][0][0]=1;
    17     for(int i=2;i<=N;++i){//枚举第i个点 
    18         for(int j=0;j<=M;++j){//已经连了j条边 
    19             for(int s=0;s<(1<<(K+1));++s){//0~2^(l+1)-1 包含i本身 
    20                 for(int c=0;c<K;++c){// i ~ i-k+c
    21                     if(f[i][j][s][c]!=0){//f[i][j][s][c]!=0来更新其他值,刷表法 
    22                         f[i][j][s][c+1]+=f[i][j][s][c]%mod;//此时不连边可直接转移 
    23                         f[i][j][s][c+1]%=mod;
    24                         if(j<M&&i-K+c>=1){
    25                             f[i][j+1][s^(1<<K)^(1<<c)][c]+=f[i][j][s][c]%mod; 
    26                             f[i][j+1][s^(1<<K)^(1<<c)][c]%=mod;
    27                             //K与c之间连一条边,其实K表示的是第i个点,c表示的是i-K+c个点,只是根据反向对称性反过来不影响答案 
    28                             //s^(1<<K)^(1<<c),使 1<<K,1<<c的位置的奇偶性取反 
    29                         }
    30                     }
    31                 }
    32                 if((s&1)==0&&f[i][j][s][K]!=0) f[i+1][j][s>>1][0]=f[i][j][s][K];//第i个点连了偶数条边可以直接给 i+1,
    33                                                                                 //s>>1相当于除掉了第i个点 
    34             }
    35         }
    36     }
    37     printf("%d",f[N+1][M][0][0]);
    38     return 0;
    39 }
     
    
    
  • 相关阅读:
    leetcode ZigZag conversion(mediium) /java
    leetcode longest palindromic substring (medium) /java
    leetcode longest substring without repeating characters(medium) /java
    leetcode two_sum (easy) /java
    think_in_java_多态
    java复用类知识
    java找不到或无法加载主类
    java程序包不存在
    集合
    列表的增删改查
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5093584.html
Copyright © 2011-2022 走看看