您的位置:首页 > 其它

好学易懂 从零开始的插头DP(一)

2020-11-22 23:33 591 查看

好学易懂 从零开始的插头DP(一)

写在前面

这是一篇,以蒟蒻视角展开的梳理总结。更改了一些顺序,变化了一些细节。方便蒟蒻学习理解(起码本蒟蒻是这样)。大佬们可以直接看其它大佬的博客,可以学的更快。

你必须要学会的前置知识:状态压缩DP
学不会依旧可以读,但是推荐学的前置知识:哈希

论文贡前面,建议读完博客再看。
《基于连通性状态压缩的动态规划问题》

什么是插头DP

很显然,是一个关于插头的动态规划。那么,什么是插头呢?

如图我们在一个方格内,关于格点画一条闭合回路。
1 #include<iostream>
2 #include<stdio.h>
3 #include<cstring>
4 using namespace std;
5 int n,m,maxk,a[13][13];
6 long long dp[13][13][1<<14];
7 void init()
8 {
9     scanf("%d%d",&n,&m);
10     maxk=(1<<(m+1))-1;
11     for (int i=1;i<=n;i++)
12     {
13         for (int j=1;j<=m;j++)
14         {
15             scanf("%d",&a[i][j]);
16         }
17     }
18     memset(dp,0,sizeof(dp));
19 }
20 void solve()
21 {
22     int prei,prej;
23     dp[0][m][0]=1;
24     for (int i=1;i<=n;i++)
25     {
26         for (int k=0;k<=maxk;k++)
27         {
28             dp[i][0][k<<1]=dp[i-1][m][k];
29         }
30         for (int j=1;j<=m;j++)
31         {
32             prei=i;
33             prej=j-1;
34             for (int k=0;k<=maxk;k++)
35             {
36                 int b1=(k>>(j-1))&1;
37                 int b2=(k>>j)&1;
38                 if (!a[i][j])
39                 {
40                     if (!b1&&!b2) dp[i][j][k]+=dp[prei][prej][k];
41                 }
42                 else if (!b1&&!b2)
43                 {
44                     dp[i][j][k+(1<<j)+(1<<(j-1))]+=dp[prei][prej][k];
45                 }
46                 else if (b1&&!b2)
47                 {
48                     dp[i][j][k]+=dp[prei][prej][k];
49                     dp[i][j][k+(1<<(j-1))]+=dp[prei][prej][k];
50                 }
51                 else if (!b1&&b2)
52                 {
53                     dp[i][j][k]+=dp[prei][prej][k];
54                     dp[i][j][k-(1<<(j-1))]+=dp[prei][prej][k];
55                 }
56                 else if (b1&&b2)
57                 {
58                     dp[i][j][k-(1<<j)-(1<<(j-1))]+=dp[prei][prej][k];
59                 }
60             }
61         }
62     }
63     printf("%lld\n",dp
[m][0]);
64 }
65 int main()
66 {
67     int t;
68     scanf("%d",&t);
69     while (t--)
70     {
71         init();
72         solve();
73     }
74     return 0;
75 }
View Code of P5074

电脑前这个努力的帅气身影是谁呢?そう 私 です

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: