본문 바로가기

Algorithm/dps

[백준][14391번][DPS] 종이 조각

스도쿠


https://www.acmicpc.net/problem/2580





<문제>







<코드>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <cstdlib>
#include <stdio.h>
 
using namespace std;
 
int arr[4][4];
 
 
int main()
{
    int n,m;
    int t,i,j,cur;
    int ans = 0;
    cin >> n >> m;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            scanf("%1d",&arr[i][j]);
 
    // 비트마스킹 기법
    for(t=0; t < ((1<<n*m)); t++)
    {
        int sum = 0;
        // 가로 일 때
        for(i=0;i<n;i++)
        {
            int psum = 0;
            for(j=0;j<m;j++)
            {
                cur = m * i + j;
                // 계속 가로면 자리 수 업!
                if((t & (1<<cur)) == 0)
                {
                    psum = 10 * psum + arr[i][j];
                }
                // 세로면 끝내고 더해주자
                else
                {
                    sum += psum;
                    psum = 0;
                }
            }
            // 마지막에 가로로 끝내면 안더해주니깐 sum에 추가해주기
            sum += psum;
        }
        // 세로 일 때는 i와 j만 바꿔주기 (검사하는 순서만 바꿔여)
        for(j=0;j<m;j++)
        {
            int psum = 0;
            for(i=0;i<n;i++)
            {
                cur = m * i + j;
                // 계속 가로면 자리 수 업!
                if((t & (1<<cur)) != 0)
                {
                    psum = 10 * psum + arr[i][j];
                }
                // 세로면 끝내고 더해주자
                else
                {
                    sum += psum;
                    psum = 0;
                }
            }
            // 마지막에 가로로 끝내면 안더해주니깐 sum에 추가해주기
            sum += psum;
        }
        if(ans<sum)
            ans = sum;
    }
    cout << ans;
}
 
cs



<문제 푼 요령>


1. 모든 경우의 수에서 각각의 칸은 가로 또는 세로의 칸으로 나뉠 수 있다는 점에 주목한다. 최대 칸의 수가 16개이므로 비트마스킹 기법으로 풀 수 있다.


2. 비트마스킹으로 풀 경우 최대 경우의 수는 2^16 * 16이므로 1억을 넘지 않는다. 처음에 가로의 경우를 조사해주고 그 다음에 세로의 경우를 조사해준다.


3. 유의할 점은 cur 값이 가로에서나 세로에서나 같은 값으로 설정되어야 한다. 왜냐하면 모든 칸들의 인덱스를 고유하게 놓고 검사하는거기 때문에 가로에서와 세로에서와 검사하는 값이 겹치면 안된다.

'Algorithm > dps' 카테고리의 다른 글

[백준][12100번][DPS] 2048 (Easy)  (0) 2019.03.19
[백준][1062번][DPS] 가르침  (0) 2019.03.14
[백준][1987번][DPS] 알파벳  (0) 2019.03.11
[백준][2580번][DPS] 스도쿠  (0) 2019.03.10
[백준][9663번][DPS] N-Queen  (2) 2019.03.09