Luo Gu P2622-- lights problems like pressure DP [II]

Topic Portal


Title Description

N conventional lamps, and m buttons. Each button can simultaneously control the lamp n - i-button is pressed, all lamps have an effect. For the first pressed i j lamp, is one of the 3 following effects: If A [i] [j] is 1, then when this lamp when opened, shut it off, otherwise no matter; If -1 then, if this lamp is off, then open it, otherwise no matter; if it is 0, regardless of whether these lights on, do not care.

Now these lights are open, given all the switches to control the effect of all the lamps, inquire at least a few Yaoan button to switch off all.


Input Format

The first two rows of two numbers, nm

Subsequently m rows, each row number n, a [i] [j] indicates the effect of the i-th switch of j-th light.


Output Format

An integer representing the minimum number press the button. If there is no way to make it all off, output -1


Entry

3
2
1 0 1
-1 1 0


Export

2


Description / Tips

For 20% of the data, no solution can score output.

Data for 20%, n <= 5

20% to the data, m <= 20

The above data points may overlap.

Data for 100% <= n 10, m <= 100


answer

  • Obviously shaped pressure DP
  • N = 10 lights up, i.e., (1 << 10) --1 states
  • Start enumeration from the fully open state, until the fully closed state;
    for each state, the enumeration switch;
    for each switch, find the state after the switch changes

    the[Status changes after] dp = min (dp [the state change], dp [to a state just] + 1);(Just as the state, only a change of state of the switch is to change after)
  • The last answer is dp [0]

AC-Code

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int mod = 1e9;

int a[101][11];
int dp[1 << 10];
int main() {
	ios;
	int n, m;
	while (cin >> n >> m) {
		for (int i = 1; i <= m; i++)
			for (int j = 1; j <= n; j++)
				cin >> a[i][j];
		memset(dp, 0x3f, sizeof(dp));
		dp[(1 << n) - 1] = 0;
		for (int i = (1 << n) - 1; i >= 0; i--) { // 枚举状态
			for (int j = 1; j <= m; j++) { // 枚举开关
				int now = i;
				for (int k = 1; k <= n; k++) { // 枚举灯
					if (!a[j][k])	continue;
					else if (a[j][k] == 1 and (i & (1 << k - 1)))
						now ^= (1 << (k - 1));
					else if (a[j][k] == -1 and !(i & (1 << k - 1)))
						now ^= (1 << k - 1);
				}
				dp[now] = min(dp[now], dp[i] + 1); // 从 i 状态,按一次开关(j)得到了 now 状态
			}
		}
		cout << (dp[0] == 0x3f3f3f3f ? -1 : dp[0]) << endl;
	}
}

Published 104 original articles · won praise 60 · views 5853

Guess you like

Origin blog.csdn.net/Q_1849805767/article/details/103580749