题解 P2040 【打开所有的灯】

SIGSEGV

2018-04-29 19:51:55

Solution

此题甚水。首先要明确:同一盏灯操作一次就够了!!!因为灯的状态与开关灯的次序无关! 接着就好办了:用一个int记录下一个二进制数,代表对灯光的操作,如样例,最优操作是动第一与第五盏灯,操作码为000010001(2) 即17. 然后这个九位二进制数到范围在0~1023之间,慢慢去凑状态吧~ 最后贴代码: ```cpp #include <bits/stdc++.h> using namespace std; int a[5][5],b[5][5],dx[] = {0,1,0,-1},dy[] = {1,0,-1,0},ans = INT_MAX; void chk(int num) //这是个检查的函数 { int cnt = 0; for (int i = 0;i < 3;i++) for (int j = 0;j < 3;j++) { if (num % 2) //此灯要戳一下 { ++cnt; b[i][j] = !b[i][j]; for (int k = 0;k < 4;k++) { int nx = i + dx[k],ny = j + dy[k]; if (nx >= 0 && ny >= 0 && nx < 3 && ny < 3) b[nx][ny] = !b[nx][ny]; } } num /= 2;//向下一位进军 } for (int i = 0;i < 3;i++) for (int j = 0;j < 3;j++) if (b[i][j] == 0) return; ans = min(ans,cnt); } int main() { for (int i = 0;i < 3;i++) for (int j = 0;j < 3;j++) scanf("%d",&a[i][j]); int mx = pow(2,10); for (int i = 0;i < mx;i++)//凑状态码 { for (int j = 0;j < 3;j++) for (int k = 0;k < 3;k++) b[j][k] = a[j][k];//不想要用memcpy,反正时间差不多 chk(i); } printf("%d",ans); return 0; } ```