zoukankan      html  css  js  c++  java
  • 奇怪的道路——状压DP

    题目描述

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

    100%的数据满足1 <= n <= 30, 0 <= m <= 30, 1 <= K <= 8.   

    简化版题意:n个点m条边,满足条件:

    1. 每个点的度为偶数。
    2. 每条边连接的顶点u,v编号之差不超过K且没有自环。

    求方案数%1000000007后的值。

    思路

      挺神的一道状压$DP$题。难点在于状态量的表示。首先我们分析数据范围,发现$K<=8$,那么很显然状态压缩的那一维和K有关,也是我们直接想到状压$DP$的一个原因。

      那么有$f[i][j][s]$表示前$i$个点,连了$j条边,编号为i-k->i$的点的状态为$s$,那么显然$s$表示的是这些点度数的奇偶性。

      然后快乐的开始推。考虑加入一条边的状态转移。然后,就没有然后了。。。。。。(本人做此题也就到此为止了)

      怎么加边?以$i$为一个端点,另一个呢?很显然这个状态不足以满足$DP$转移,我们需要再加一维,表示当前的$i$向哪个点连边。又因为顶点编号之差$<=k$,我们只需要考虑$i向区间[i-k,i-1]$的连边就可以了。那么有$f[i][j][s][l]表示前i个点,连了j条边,[i-k,i]的状态为s,处理当前点i和i-k+l$之间的连边。

      转移不是特别难(这里采用刷表):

    1. $i和i-k+l不连边,有f[i][j][s][l+1]+=f[i][j][s][l]$
    2. $i和i-k+l$连边,有$f[i][j+1][s$ $ oplus$ $1<<k$ $oplus$ $1<<l][l]+=f[i][j][s][l]$
    3. 考虑增加一个点,那么必须有:编号为$i-k$的点度数为偶数,$[i-k,i-1]$区间的点和i已经全部转移

      答案就是$f[n][m][0][k]$前$n$个点连接了$m$条边,当且处理的是$n-k+k=n$,即$[n-k,n-1]$全部处理完的情况。

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int p=1000000007;
    const int S=1<<9;
    int f[35][35][S][35];
    int n,m,k;
     
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        f[2][0][0][0]=1;//初始化,1,2间没有连边也是一种方案 
        for(int i=2;i<=n;i++)
        for(int j=0;j<=m;j++)
        for(int s=0;s<(1<<k+1);s++)//枚举状态 
        {
            for(int l=0;l<k;l++)//枚举i-k+l
            {
                f[i][j][s][l+1]+=f[i][j][s][l]%=p;//不连边 
                if(i-k+l>0&&j<m)f[i][j+1][s^(1<<l)^(1<<k)][l]+=f[i][j][s][l]%=p;//连边 
            }
            if(!(s&1))f[i+1][j][s>>1][0]+=f[i][j][s][k]%=p;//把i-k删去,加入i+1 
        }
        cout<<f[n][m][0][k];
    }
  • 相关阅读:
    BZOJ3884 上帝与集合的正确用法 【欧拉定理】
    BZOJ4872 [六省联考2017]分手是祝愿 【期望dp】
    BZOJ4650 [NOI2016]优秀的拆分 【后缀数组】
    BZOJ1562 [NOI2009]变换序列 【KM算法】
    BZOJ2657 [Zjoi2012]旅游(journey) 【树的直径】
    BZOJ3999 [TJOI2015]旅游 【树剖 + 线段树】
    BZOJ3997 [TJOI2015]组合数学 【Dilworth定理】
    BZOJ4823 [Cqoi2017]老C的方块 【最小割】
    坐标系统
    利用键盘左右键使图像左右移动,上下键使图像的两个纹理可见度比例上下调整
  • 原文地址:https://www.cnblogs.com/THRANDUil/p/11588372.html
Copyright © 2011-2022 走看看