백준문제풀이
백준 문제 14927번 전구 끄기 문제풀이 c++
노가다 김씨
2022. 3. 20. 21:59
https://www.acmicpc.net/problem/14927
14927번: 전구 끄기
홍익이는 N x N 전구 판을 가지고 있다. 전구 판에는 각 칸마다 전구가 하나씩 연결되어 있다. 이 전구 판에서 하나의 전구를 누르면, 해당 전구를 포함하여 상하좌우의 총 5개 전구들의 상태가 변
www.acmicpc.net
문제해석
N이 최대 18개이라 그냥 브루트 포스를 하면 2^324번 해야해서 당연히 아닐거고.. 어떻게 해야하나 고민하다 모르겠어서 구글링해서 찾아보았다.
찾아본결과 그리디로 풀수있는 문제였다.
브루트포스를 맨 윗줄 하나에 대해서만 수행한 후 아랫줄로 내려가서 윗 전구가 켜져있으면 윗 전구를 꺼주는 것을 마지막 라인까지 하면 되는것이다.
그 후 모든 전구가 꺼져있다면 이전 최소값과 비교하여 더 작은것으로 업데이트해주는것이다.
어떻게 이것이 최적해를 어떻게 보장해주는지 증명을 어떻게해야하나 너무 어려운거같다.
아무튼 위 방식대로하면 맨윗줄만 모든 경우를 하니까 2^18가지의 경우밖에없어서 시간초과가 안나고 아래와 같이 코드를 작성하였다.
코드
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void setting();
void copy();
void dfs(int index,int size,int depth);
bool check();
bool inside(int ny,int nx);
vector <int> v;
bool visited[18];
int dy[4]={0,0,1,-1};
int dx[4]={1,-1,0,0};
bool base[18][18];
bool a[18][18];
int N;
int ans=9999;
int main(){
cout.tie(NULL);
cin.tie(NULL);
ios_base::sync_with_stdio(false);
setting();
for(int i=0; i<=N; i++)
{
dfs(0,i,0);
}
if(ans==9999)
{
cout<<-1;
}
else
{
cout<<ans;
}
}
void setting(){
cin>>N;
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
cin>>base[i][j];
}
}
}
void copy(){
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
a[i][j]=base[i][j];
}
}
}
void dfs(int index,int size,int depth){
if(depth==size)
{
copy();
int ny;
int nx;
int cnt=0;
for(int i=0; i<v.size(); i++)
{
a[0][v[i]]=!a[0][v[i]];
cnt++;
for(int j=0; j<4; j++)
{
ny=dy[j];
nx=v[i]+dx[j];
if(inside(ny,nx))
{
a[ny][nx]=!a[ny][nx];
}
}
}
for(int i=1; i<N; i++)
{
for(int j=0; j<N; j++)
{
if(a[i-1][j]==1)
{
a[i][j]=!a[i][j];
cnt++;
for(int k=0; k<4; k++)
{
ny=i+dy[k];
nx=j+dx[k];
if(inside(ny,nx))
{
a[ny][nx]=!a[ny][nx];
}
}
}
}
}
if(check())
{
ans=min(ans,cnt);
}
return;
}
for(int i=index; i<N; i++)
{
if(visited[i]==0)
{
visited[i]=1;
v.push_back(i);
dfs(i,size,depth+1);
v.pop_back();
visited[i]=0;
}
}
}
bool check(){
for(int i=0; i<N; i++)
{
if(a[N-1][i]==1)
{
return false;
}
}
return true;
}
bool inside(int ny,int nx){
if(0<=ny&&ny<N&&0<=nx&&nx<N)
{
return true;
}
else
{
return false;
}
}