zoukankan      html  css  js  c++  java
  • HDU 3091 Necklace <<状压dp

    题意

    要把一些珠子串成一串,每个珠子只可以和限制特定的别的珠子串在一起,给定珠子数量和限制条件,求能组成的不同的项链的种数。

    思路

    看数据范围,再加上这是有限制条件的问题求解,很容易发现是状压dp的问题。dp[i][j]表示放下第i个珠子后的状态为j(即i为前一个珠子),只要保证下一个珠子能和前一个接的上就可行。那么枚举k为下一个珠子,看是否可行即可,具体看代码。然后细节上,点的下标与dp中的状态要统一起来才不会出错。

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 long long dp[20][1<<18];
     4 int G[20][20];//数据范围小,只需要判断是否邻接,所以矩阵很方便
     5 int main()
     6 {
     7     int n,m;
     8     while(~scanf("%d%d",&n,&m))
     9     {
    10         memset(dp,0,sizeof(dp));
    11         memset(G,0,sizeof(G));
    12         for(int i=0,a,b;i<m;i++)
    13         {
    14             scanf("%d%d",&a,&b);
    15             G[a][b]=G[b][a]=1;//这里没统一下标,所以后面写的时候出现了很多麻烦
    16         }
    17         dp[0][1]=1;//因为是个环,所以任意选取一颗珠子作为开头,此处选1
    18         for(int i=1;i<(1<<n);i++)
    19         {
    20             for(int j=0;j<n;j++)
    21             {
    22                 if(dp[j][i]==0) continue;//如果此状态不可达,跳过
    23                 for(int k=0;k<n;k++)
    24                 {
    25                     if(i&(1<<k)) continue;//如果这个珠子已经放了,跳过
    26                     if(G[k+1][j+1]) dp[k][i|(1<<k)]+=dp[j][i];//如果k与j(前一个珠子)能接上,就可以状态转移
    27                 }
    28             }
    29         }
    30         long long ans=0;
    31         for(int i=0;i<=n;i++)
    32         {
    33             if(G[1][i+1])//看最后一颗珠子与第一颗是否连的起来
    34                 ans+=dp[i][(1<<n)-1];
    35         }
    36         printf("%lld
    ",ans);
    37     }
    38 }

    后记

    这题一开始用了三维dp,多了一维表示第一个珠子,然后最后再除阶乘得出答案,然而事实上由于是个环,所以从哪个珠子开始关系并不大。从这题上还是学到了很多的。

  • 相关阅读:
    Go基础系列:双层channel用法示例
    shell脚本动画小工具
    Go基础系列:channel入门
    python面向对象入门(1):从代码复用开始
    python包导入细节
    python模块导入细节
    Go基础系列:读取标准输入
    黄聪:C#获取网页HTML内容的三种方式
    黄聪:如何正确在Vue框架里使用Swiper
    黄聪:C#使用GeckoFx拦截监控Http数据
  • 原文地址:https://www.cnblogs.com/computer-luo/p/10061659.html
Copyright © 2011-2022 走看看