The principle and details of state compression DP are not supplemented and introduced here. The focus is to show you the complete AC code and realize in-depth understanding through exquisite and simplified source code.
(if you don't know what shape pressure dp is, you can refer to other big guys' blogs (* ^ - ^) ρ (*╯^╰))
Brief description and introduction:
In fact, the essence of shape pressure dp is based on a violent enumeration algorithm, but it records and stores the operation with the help of bit masking bit operation and binary 0-1 characteristics to improve the efficiency of the algorithm.
Note:
There are usually two models:
1. Set class (weighted graph, etc.):
e.g.TSP, Hamilton distance, CPP (China Postal road problem)
2. Connectivity class \ checkerboard class:
e.g.Corn Fields, artillery array, Mondriaan's Dream, chessboard filling, little king
TIP:
1. Preprocess dp and save all legal transfer schemes;
2. Initialize, establish the state transition equation and start the transition;
Service conditions:
1. The essence is to n! For violent traversal, the requirement n is not very large;
2. Preprocessing and initialization shall be correct;
3. Find the key and analyze the correct state transition equation;
4. Master bit masking operation skills and binary bit operation rules;
5. Some must have local optimal substructures;
6. The reference of state number k\cnt and the use of state array of state set can greatly improve the efficiency of optimization execution;
(next, we will directly add several examples of the code, all of which are self-written and perfect simplified code. The source of the problem can be found through the search engine. Similarly, the principle analysis is the same. Is this the simplified and exquisite code recording ac, or is it the purest reading of the source code to improve your understanding {{(> <)}})
Typical example:
1.Travelling Salesman Problem
/* In the case of small scale, the classical NP-C problem TSP uses the pressure DP to solve the state transition equation, preprocessing bit operation and local optimal substructure directed graph */ //In essence, it is also a kind of violent traversal, that is, the enumeration algorithm, which uses the bit masking state compression technique to reduce n! Complexity of //State pressure dynamic programming bottom-up #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int INFTY = 0x3f3f3f3f; const int N = 15 + 5; const int M = 1 << N; int dp[N][M]; int graph[N][N]; int main() { int v, e; cin >> v >> e; memset(graph, INFTY, sizeof(graph)); for (int i = 0; i < e; i++) { int s, t, d; cin >> s >> t >> d; graph[s][t] = d; } memset(dp, INFTY, sizeof(dp)); int ans = INFTY; for (int t = 0; t < v; t++) { memset(dp, INFTY, sizeof(dp)); dp[(1 << v) - 1][t] = 0; for (int s = (1 << v) - 2; s >= 0; s--) { for (int i = 0; i < v; i++) { for (int j = 0; j < v; j++) { if (!((s >> j) & 1)) { dp[s][i] = min(dp[s][i], dp[s | (1 << j)][j] + graph[i][j]); } } } } ans = min(ans, dp[0][t]); } cout << (ans == INFTY ? -1 : ans) << endl; return 0; }
2.Chinese Postman Problem
/* CCP Construction of connected graph class state compression DP problem transformation Euler loop and DP Floyd algorithm of repeated (parallel) edges point to shortest path recursion */ #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int maxn = 0xffffff; const int N = 15 + 5; int deg[N]; int dp[1 << N]; int graph[N][N]; int n, m; void floyd() { for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j]); } } } } int search(int state) { if (state == 0)return 0; if (dp[state])return dp[state]; int ans = maxn; int temp; for (int i = 0; i < n - 1; i++) { if (state & (1 << i)) { for (int j = i + 1; j < n; j++) { if (state & (1 << j)) { temp = search(state - (1 << i) - (1 << j)) + graph[i][j]; ans = min(ans, temp); } } } } return dp[state] = ans; } int main() { while (cin >> n >> m && n) { int sum = 0; int state = 0; int x, y, w; memset(dp, 0, sizeof(dp)); memset(deg, 0, sizeof(deg)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { graph[i][j] = maxn; } } while (m--) { cin >> x >> y >> w; graph[x][y] = graph[y][x] = min(graph[x][y], w); deg[x]++; deg[y]++; sum += w; } floyd(); for (int i = 0; i < n; i++) { if (deg[i] & 1) { state |= (1 << i); } } sum += search(state); cout << sum << endl; } return 0; }
3.Corn Fields
/* Classical chessboard like pressure DP binary bit operation bit masking skill 0 1 indicates the importance of selecting skill state number variable optimization efficiency state transition equation preprocessing */ #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 12 + 5; const int M = 1 << N; const int mod = 1000000000; int dp[N][M]; int graph[M]; int state[M]; bool judge1(int x) { return (bool)(x&(x << 1)); } bool judge2(int x, int y) { return (bool)(graph[x] & state[y]); } int main() { int n, m; while (cin >> n >> m && n) { memset(dp, 0, sizeof(dp)); memset(state, 0, sizeof(state)); memset(graph, 0, sizeof(graph)); int x = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> x; //Skills of 0 1 using state compressed binary Tags if (x == 0) { graph[i] += (1 << j); } } } int k = 0; for (int i = 0; i < (1 << m); i++) { if (!judge1(i)) { state[k++] = i; } } //Pretreatment for (int i = 0; i < k; i++) { if (!judge2(0, i)) { dp[0][i] = 1; } } for (int i = 1; i < n; i++) { for (int j = 0; j < k; j++) { if (judge2(i, j))continue; for (int f = 0; f < k; f++) { if (judge2(i - 1, f))continue; if (!(state[j] & state[f])) { dp[i][j] += dp[i - 1][f]; dp[i][j] %= mod; } } } } int ans = 0; for (int i = 0; i < k; i++) { ans += dp[n - 1][i]; ans %= mod; } cout << ans << endl; } return 0; }
4.Mondriaan's Dream
/* State compression DP binary bit operation bit masking technique state transition equation preprocessing violence enumeration optimization method */ #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int N = 12; const int M = 1 << N; long long f[N][M]; bool state[M]; int main() { int n, m; while (scanf("%d%d", &n, &m) == 2 && n) { for (int i = 0; i < 1 << n; i++) { state[i] = 1; int cnt = 0; for (int j = 0; j < n; j++) { if ((i >> j) & 1) { if (cnt & 1)state[i] = 0; cnt = 0; } else { cnt++; } } if (cnt & 1)state[i] = false; } memset(f, 0, sizeof(f)); f[0][0] = 1; for (int i = 1; i <= m; i++) { for (int j = 0; j < 1 << n; j++) { for (int k = 0; k < 1 << n; k++) { if (((j&k) == 0) && (state[j | k])) { f[i][j] += f[i - 1][k]; } } } } cout << f[m][0] << endl; } return 0; }
5. Artillery array
/* Artillery array classic chessboard like pressure DP complex class simulation binary bit operation bit masking technique preprocessing triplet represents double-layer influence state transition */ //0 1 inverse indicates the "chessboard" state, which is highly skilled and easy to judge by bit operation (&) //Instead of the traditional scheme number problem, a shell is added to find the maximum solution, and the introduction and optimization efficiency of dp representation and judgment state number k/num are increased #include <algorithm> #include <iostream> #include <cstring> using namespace std; const int N = 100 + 5; const int maxn = 1 << 11; int dp[N][maxn][maxn]; int state[maxn], num[maxn]; int graph[N]; int n, m, p; bool check(int x) { if (x&(x << 1))return false; if (x&(x << 2))return false; return true; } int count(int x) { int temp = 0; int i = 1; while (i <= x) { if (i&x)temp++; i <<= 1; } return temp; } //Preprocessing out legal status void init() { p = 0; memset(state, 0, sizeof(state)); memset(num, 0, sizeof(num)); for (int i = 0; i < 1 << m; i++) { if (check(i)) { state[p++] = i; num[p++] = count(i); } } } int main() { while (cin >> n >> m && n) { char ch; memset(dp, 0, sizeof(dp)); memset(graph, 0, sizeof(graph)); //Initialize checkerboard for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> ch; if (j) { graph[i] <<= 1; } if (ch == 'H') { graph[i] |= 1; } } } init(); //First two lines of preprocessing for (int i = 0; i < p; i++) { if (!(graph[0] & state[i])) { dp[0][i][0] = num[i]; } } for (int i = 0; i < p; i++) { if (!(graph[1] & state[i])) { for (int j = 0; j < p; j++) { if (!state[i] & state[j]) { dp[1][i][j] = max(dp[1][i][j], dp[0][j][0] + num[i]); } } } } //Global simulation for (int i = 2; i < n; i++) { for (int k = 0; k < p; k++) { if (!(graph[i] & state[k])) { for (int j = 0; j < p; j++) { if (!(graph[i - 1] & state[j])) { if (!(state[k] & state[j])) { for (int f = 0; f < p; f++) { if (!(graph[i - 2] & state[f])) { if (!(state[f] & state[j])) { if (!(state[f] & state[i])) { dp[i][k][j] = max(dp[i][k][j], dp[i - 1][j][f] + num[k]); } } } } } } } } } } int ans = 0; for (int i = 0; i < p; i++) { for (int j = 0; j < p; j++) { ans = max(ans, dp[n - 1][i][j]); } } cout << ans << endl; } return 0; }
That's all the foreshadowing Д °;)っ)