关灯问题II 洛谷2622

https://www.luogu.org/problemnew/show/P2622

状态压缩DP

设$f(state)$表示当前开的灯是$state$时,关掉这些灯需要的最少步数

转移则是

#f(state)=min_{i=1}^m {f(buttons[i].operate(state))+1}#

代码


#include <iostream> #include <algorithm> #include <string> #include <cinttypes> using int_t = long long int; using std::cin; using std::cout; using std::endl; int_t n, m; std::string binary(int_t x, int_t size); struct Button { uint32_t on; uint32_t off = (~0); inline int_t operate(int_t state) { // cout << "state " << binary(state, n) << " opted = " << binary(state & off | on, n) << endl; return (state & off) | on; } } buttons[101]; // int_t search(int_t state) // { // static int_t memory[1030]; // static bool visited[1030]; // static bool visiting[1030]; // if (state == 0) // return 0; // visiting[state] = true; // if (visited[state]) // { // return memory[state]; // } // int_t result = 0x7ffffffffll; // for (int_t i = 1; i <= m; i++) // { // auto temp = buttons[i].operate(state); // if (visiting[temp]) // continue; // // auto result = ; // // cout << "searching state " << binary(temp, n) << " result = " << search(temp) << endl; // result = std::min(result, search(temp) + 1); // } // visiting[state] = false; // if (result == 0) // { // return 0x7ffffffffll; // } // visited[state] = true; // return memory[state] = result; // } std::string binary(int_t x, int_t size) { std::string result; for (int_t i = size - 1; i >= 0; i--) { result += (((x & (1 << i)) != 0) + '0'); } return result; } int main() { cin >> n >> m; for (int_t i = 1; i <= m; i++) { auto &button = buttons[i]; for (int_t j = 0; j < n; j++) { int_t opt; cin >> opt; if (opt == -1) { button.off ^= (1 << (j)); } else if (opt == 1) { button.on |= (1 << (j)); } } // cout << "button " << i << " on:" << binary(button.on, n) << " off:" << binary(button.off, n) << endl; } static int_t dp[1030]; std::fill(dp + 1, dp + (1 << n), 0x7fffffff); for (int_t i = 0; i < (1 << n); i++) { for (int_t j = 1; j <= m; j++) { auto &button = buttons[j]; auto state = button.operate(i); dp[state] = std::min(dp[state], dp[i] + 1); } } auto result = dp[(1 << n) - 1]; if (result >= 0x7fffffff) cout << -1; else cout << result << endl; return 0; }

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理