DP(状压专题三)

it2022-05-05  118

题意 :给定n个灯,m个开关, 以及每个开关的效果, 要求灭掉所有的灯至少需要多少次

>> face <<

Strategy:状压DP, i是一个表示二进制的十进制数,'1’表示开灯

状态: dp[i] 达到状态’i’ 最少需要多少次

目标: dp[0] -> 全灭

边界: dp[(1 << n) - 1 ] = 1 ;其余全部初始成无穷

合法判断: 默认所有状态合法

转移方程:

d p [ i ] = m i n ( d p [ i ] , d p [ j ] + 1 ) dp[i] = min(dp[i], dp[j] + 1) dp[i]=min(dp[i],dp[j]+1)

attention: 倒叙枚举

双倍经验: 注意枚举的边界, 位运算的优先级 (判断某一位是否是0不能用xor)

#include <bits/stdc++.h> // #include<bits/extc++.h> // #define oo INT_MAX #define _rep(i, a, b) for (int i = (a); i <= (b); ++i) #define _rev(i, a, b) for (int i = (a); i >= (b); --i) #define _for(i, a, b) for (int i = (a); i < (b); ++i) #define _rof(i, a, b) for (int i = (a); i > (b); --i) #define ll long long #define all(x) x.begin(), x.end() #define db double #define eps 0.00001 #define met(a, b) memset(a, b, sizeof(a)) #define lowbit(x) x &(-x) #define cost first #define what_is(x) cerr << #x << " is " << x << endl; #define val second #define oo 0x3f3f3f3f #define pi acos(-1.0) using namespace std; const int maxn = 1 << 11; int dp[maxn]; int matrix[103][12]; int main() { int n, m; cin >> n >> m; _rep(i, 1, m) { _rep(j, 1, n) { cin >> matrix[i][j]; } } memset(dp, oo, sizeof(dp)); dp[(1 << n) - 1] = 0; _rev(i, (1 << n) - 1, 0) { _rep(j, 1, m) //开关 { int state = i; _rep(k, 1, n) //灯 { if (matrix[j][k] == 0) continue; if (matrix[j][k] == 1 && ((i >> (k - 1)) & 1)) { state ^= 1 << (k - 1); } if (matrix[j][k] == -1 && !((i >> (k - 1)) & 1)) { state ^= 1 << (k - 1); } } dp[state] = min(dp[state], dp[i] + 1); } } printf("%d\n", dp[0] == oo ? -1 : dp[0]); }

最新回复(0)