• BZOJ 1231 [Usaco2008 Nov]mixup2 混乱的奶牛:状压dp + 滚动数组


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1231

    题意:

      给你n个数字s[i],问你有多少个排列,使得任意相邻两数字之差的绝对值大于m。

    题解:

      表示状态:

        dp[i][j][state] = arrangements

        i:考虑到第i个位置。

        j:上一个数字是s[j]。(j = n表示没有上一个数字)

        state:表示哪些数字已经被选过。

      找出答案:

        ans = ∑ dp[n][j][(1<<n)-1]

      如何转移:

        now: dp[i][j][state]

        枚举第i个位置要放数字s[k]。

        dp[i+1][k][state|(1<<k)] += dp[i][j][state]

        转移条件:

          (1)abs(s[j]-s[k])>m || j==n

            与上一个数字之差的绝对值 > m,或没有上一个数字。

          (2)!((state>>k)&1)

            数字s[k]还没被选过。

      边界条件:

        dp[0][n][0] = 1

        others = 0

      优化:

        因为dp要用long long存,空间正好爆了。。。

        第一维改成滚动数组。

        注意:当前为dp[i&1],要用dp[(i+1)&1],要把dp[(i+1)&1]全部设为0。

          即:memset(dp[(i+1)&1],0,sizeof(dp[(i+1)&1]))

    AC Code:

     1 // state expression:
     2 // dp[i][j][state] = arrangements
     3 // i: considering ith pos
     4 // j: last cow
     5 // state: state of selection
     6 //
     7 // find the answer:
     8 // sigma dp[n][j][(1<<n)-1]
     9 //
    10 // transferring:
    11 // now: dp[i][j][state]
    12 // dp[i+1][k][state|(1<<k)] += dp[i][j][state]
    13 // abs(s[j]-s[k])>m || j==n
    14 // !((state>>k)&1)
    15 //
    16 // boundary:
    17 // dp[0][n][0] = 1
    18 // others = 0
    19 #include <iostream>
    20 #include <stdio.h>
    21 #include <string.h>
    22 #include <stdlib.h>
    23 #define MAX_N 17
    24 #define MAX_S 65540
    25 
    26 using namespace std;
    27 
    28 int n,m;
    29 int s[MAX_N];
    30 long long ans=0;
    31 long long dp[2][MAX_N][MAX_S];
    32 
    33 void read()
    34 {
    35     cin>>n>>m;
    36     for(int i=0;i<n;i++)
    37     {
    38         cin>>s[i];
    39     }
    40 }
    41 
    42 void solve()
    43 {
    44     memset(dp,0,sizeof(dp));
    45     dp[0][n][0]=1;
    46     for(int i=0;i<n;i++)
    47     {
    48         memset(dp[(i+1)&1],0,sizeof(dp[(i+1)&1]));
    49         for(int j=0;j<=n;j++)
    50         {
    51             for(int state=0;state<(1<<n);state++)
    52             {
    53                 if(dp[i&1][j][state])
    54                 {
    55                     for(int k=0;k<n;k++)
    56                     {
    57                         if((abs(s[j]-s[k])>m || j==n) && !((state>>k)&1))
    58                         {
    59                             dp[(i+1)&1][k][state|(1<<k)]+=dp[i&1][j][state];
    60                         }
    61                     }
    62                 }
    63             }
    64         }
    65     }
    66     for(int i=0;i<n;i++)
    67     {
    68         ans+=dp[n&1][i][(1<<n)-1];
    69     }
    70 }
    71 
    72 void print()
    73 {
    74     cout<<ans<<endl;
    75 }
    76 
    77 int main()
    78 {
    79     read();
    80     solve();
    81     print();
    82 }
  • 相关阅读:
    107. Binary Tree Level Order Traversal II
    108. Convert Sorted Array to Binary Search Tree
    111. Minimum Depth of Binary Tree
    49. Group Anagrams
    使用MALTAB标定实践记录
    442. Find All Duplicates in an Array
    522. Longest Uncommon Subsequence II
    354. Russian Doll Envelopes
    opencv 小任务3 灰度直方图
    opencv 小任务2 灰度
  • 原文地址:https://www.cnblogs.com/Leohh/p/7624677.html
Copyright © 2020-2023  润新知