状压dp

Posted caterpillor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状压dp相关的知识,希望对你有一定的参考价值。

P2915 [USACO08NOV]Mixed Up Cows G

dfs去做

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define ll long long
using namespace std;
int b[25],n,m,a[25];
ll cnt;
void dfs(int t, int p){
  if(t > n){
    cnt++;
    return;
  }
  for( int i = 1; i <= n; i++){
    if( !b[i] && abs(a[i] - a[p]) > m){
      //cout << i << p << endl;
      b[i] = 1;
      dfs(t+1, i);
      b[i] = 0;
    }
  }
}
int main(){
  scanf ("%d%d", &n, &m);
  for(int i = 1 ; i <= n ; i++ )
    scanf("%d", &a[i]);
  for(int i = 1; i <= n; i++){
    memset(b, 0, sizeof b);
    b[i] = 1;
    dfs(2,i);
  }
  printf("%lld
", cnt);
  return 0;
}
dp[i][j]表示目前有i的人的队列状态,最后站过去的是j编号的人
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define  ll long long
using namespace std;
int n , m , a[ 20 ];
ll dp[ (1 << 16 ) + 5 ][ 20 ] ;
int main(){
  scanf ( "%d%d" , &n , &m ) ;
  for( int i = 1 ; i <= n ; i++ )
    scanf ( "%d" , & a[ i ] );
  ll sta = ((1 << n) - 1);
  //初始化是什么?
  for(int i = 1; i <= n; i++)
    dp[1 << (i-1)][i] = 1ll;
  for(int i = 0; i <= sta; i++)
    for(int j = 1; j <= n; j++)
      for(int k = 1 ; k <= n; k++){ //均超过k
        if((( 1 << (k-1)) | i) == i  && (i & (1 << (j - 1))) == 0  &&  abs(a[k] - a[j]) > m)
        dp[i | (1 << (j - 1))][j] += dp[i][k];
      }
  //答案是什么
  long long sum = 0 ;
  for( int i = 1; i <= n; i++)
   sum += dp[sta][i] ;
  printf("%lld
", sum);
  return 0;
}

以上是关于状压dp的主要内容,如果未能解决你的问题,请参考以下文章

POJ1699 Best Sequence(AC自动机+状压DP)

状压DP之初尝插头DP

集合划分(状压DP)

dp-状压dp

动态规划---状压dp

种植方案(状压dp)