HDU1438 鑰匙計數(狀壓dp)

原題鏈接

http://acm.hdu.edu.cn/showproblem.php?pid=1438

題面

在這裏插入圖片描述

題意

一把鎖匙有NN個槽,槽深爲12341,2,3,4。每鎖匙至少有33個不同的深度且至少有11對相連的槽其深度之差爲33。求這樣的鎖匙的總數。

思路

因爲狀態只有441<<4(1<<4),所以考慮狀壓dpdp(暴力)
dp[i][j][k][f]dp[i][j][k][f]表示前i個槽深度爲jj且第ii個槽深度爲kk的數量,ff表示是否有相連的槽差爲33

參考代碼

/* CF was purple years ago!
 * Thanks cf-tool!
 * Author: nuoyanli
 * Time: 2020-02-29 21:50:05
 **/
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'
#define PB push_back
#define FI first
#define SE second
#define m_p(a, b) make_pair(a, b)
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1
#define T(t) while (t--)
#define inf 0x3f3f3f3f
typedef long long LL;
const double pi = acos(-1.0);
const double eps = 1e-9;
const int N = 2e6 + 10;
const int M = 1e5 + 10;
const int mod = 1e9 + 7;
const int st = (1 << 10);
LL dp[1 << 5][1 << 4][1 << 2][1 << 1]; // dp[i][j][k][f]表示前i個槽深度爲j且第i個槽深度爲k的數量,f表示是否有相連的槽差爲3
void solve() {
  IOS;
  dp[1][1][0][0] = dp[1][2][1][0] = dp[1][4][2][0] = dp[1][8][3][0] = 1;//初始只有1 2 3 4這 四種狀態,分別用1 10 100 1000 表示
  for (int i = 2; i < (1 << 5); i++) {
    for (int j = 0; j < (1 << 4); j++) {
      for (int k = 0; k < (1 << 2); k++) {
        for (int st = 0; st < (1 << 2); st++) {
          if (abs(st - k) == 3) {
            dp[i][j | (1 << k)][k][1] += dp[i - 1][j][st][0];
          } else {
            dp[i][j | (1 << k)][k][0] += dp[i - 1][j][st][0];
          }
          dp[i][j | (1 << k)][k][1] += dp[i - 1][j][st][1];
        }
      }
    }
  }
  cout << "N=2: 0" << endl;
  for (int i = 3; i < (1 << 5); i++) {
    LL ans = 0;
    for (int j = 0; j < (1 << 2); j++) {
      ans += (dp[i][7][j][1] + dp[i][11][j][1] + dp[i][13][j][1] + dp[i][14][j][1] + dp[i][15][j][1]);//至少存在三種不同的鑰匙的符合存在相連差爲3的數量 0111 1011 1101 1110 1111
    }
    cout << "N=" << i << ": " << ans << endl;
  }
}
signed main() {
  solve();
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章