관리 메뉴

풀이 보관함

[C++] 백준 1034번: 램프 본문

problem solving/백준

[C++] 백준 1034번: 램프

viin 2024. 3. 30. 21:09

🔗 문제

1034번: 램프

 

1034번: 램프

첫째 줄에 N과 M이 주어진다. N은 행의 개수이고, M은 열의 개수이다. N과 M은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 램프의 상태가 주어진다. 1이 켜져있는 상태이고, 0이 꺼져

www.acmicpc.net

 

✏️ 풀이

불을 하나 켤 때마다 모든 열을 돌면서 켜야 할 생각에 아주아주 막막했다.

발상을 못 해내서 도움을 받았다...

그래서 이해하기 위해서 풀이를 쓴다!!!!!

 

 


✔️ 단계1

정답은 열에 있지 않고, 행이다. 행에 위치한 램프가 모두 켜졌는지 (행 완성) 아닌지가 정답을 좌우한다.

만약에 여러 행이 주어졌을 때 중복되는 행이 있다고 생각해보자.

어딜 켜든 똑같이 생긴 행들은 함께 상태가 바뀐다.

만약 똑같이 생긴 행1,2,3 중에 1이 다 켜진 상태면? 2, 3도 켜진 상태다. 똑같이 생긴 애들을 다시 확인할 필요가 없다.

그래서 똑같이 생긴 행들의 최대개수를 세어주는 작업이 필요하다. 

 

 

[필요한 로직]

이 작업은 그냥 뚝딱 map한테 맡겨버리자.

if(map.find(input) != map.end())
{
	++map[input]; // incr
}
else
{
	map[input] = 1; // add
}

 

✔️ 단계 2

누를 수 있는 횟수가 정해져있다. K번을 눌러서 행이 완성되지 않을 수도 있다는 말이다.

우리는 행만 바라보기로 했으니까 행을 들여다 보자.

01010101 -> 4번 눌러야 한다.
11111 -> 안 눌러도 된다.
00000 -> 5번 눌러야 한다.
1001 -> 2번 눌러야 한다.
1011 -> 1번 눌러야 한다. 

→ 행이 가진 zero의 개수가 행완성을 결정 짓는군.. !

 

 

이걸 우리가 주어진 K 와 엮어보자.

 

만약 K가 2라면?

01010101 -> 4번 눌러야 하지만 횟수가 모자라다.
11111 -> 누르는 순간 망가진다...?? 아니다. 같은 곳을 여러번 눌러서 toggle 시키면 된다. 
00000 -> 5번 눌러야 하는데 모자라다.
1001 -> 2번 눌러야 한다-> 만족
1011 -> 같은 곳을 2번 눌러서 만족가능하다.

이렇게 같은 곳을 여러번 눌러서 만족 시킬 수 있다.

 

여기서 k의 개수가 zero 이상이어야 하는 조건을 가진다는 걸 알 수 있다.

if(k >= zero) 

 

 

K가 3이라면?

01010101 -> X
11111 -> X
00000 -> X
1001 -> X
1011 -> X

2로 딱 떨어질 때랑은 다른 결과가 된다!! zero %2 == k%2 이어야지 toggle할 수 있는 상태다.

 

 

[행 완성 조건]

if(k>=zero && k%2 == zero%2)

단계1, 단계2를 합치면 시간초과 없이 문제를 풀 수 있다.

 

 

 

시간 복잡도

  • 입력 : N*M
  • 풀이 : N*M + N
    • 모든 행에 대한 N에대해서
      • M번 돌며 zero 카운팅
    • 저장된 모든 map을 돌며 최대값 구하기
      • 최악의 경우 N번

총 : NM + NM + N

 

 

 

💾  소스

#include <iostream>
#include <string>
#include <map>

const int MAX = 50 + 1;

int main()
{
    int N, M, K, answer = 0;
    std::string input[MAX];
    std::map<std::string, int> map;
    
    //input
    std::cin >> N >> M;
    for(int i=0; i<N; ++i)
        std::cin >> input[i];
    std::cin >> K;
    
    //solve
    for(int i=0; i<N;++i)
    {
        if(map.find(input[i]) != map.end())
        {
            ++map[input[i]];
        }
        else
        {
            int zero = 0;
            for(int j=0; j<M; ++j)
            {
                if(input[i][j] == '0')
                    ++zero;
            }
            
            if((zero<=K) && (zero%2 == K%2))
            {
                map[input[i]] = 1;
            }
        }
    }
    
    for(const auto& [key, value] : map)
    {
        answer = (answer > value ? answer : value);
    }
    
    //output
    std::cout << answer;
    return 0;
}