본문 바로가기

PS - 알고리즘

22204 - Tiny - 4

문제 번역

더보기

테트리스에서 몇가지 조건이 변경되었습니다.

1. 게임 판은 9*9입니다.

2. 블럭은 회전이 불가능하고 떨어지는 동안 움직일 수 없습니다.

3. 블럭은 9 종류가 있습니다.

4. 블럭이 떨어지는 순서가 있을 때 모든 블럭을 다 떨어트려야 합니다.

step 1

더보기

이 문제는 지금까지의 문제와 결이 살짝 다릅니다. 게임 판이 주어졌을 때 해당 게임 판이 얼마나 좋은지 점수를 매겨봅시다. 이 점수가 좋은 쪽을 따라가다 보면 게임을 끝낼 수 있습니다.

step 2

더보기

3가지 기준을 세웁니다.

1. 비어있는 가로줄 당 20점

2. 블럭을 놓았을 때 제거되는 가로줄 당 90점

3. 빈칸 위에 블럭이 있는 경우 블럭 개수 당 -5점

 

앞으로 올 4개의 블럭을 놓을 수 있는 경우의 수는 $9^4$입니다. 모든 경우에 대해 블럭을 내려보고 가장 점수가 높은 곳으로 떨어트립니다.

코드

더보기
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<string>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int b[60000];
int mapp[10][30],tmp[10][30],step[10];
int block[9][3][3],err=0;
int dp[10], ans[60000];
int removeS = 90, height = 20,hard = 5;
int drop(int bl, int po) {
    if (bl == 4 && po >= 7) {
        err = 1;return 0;
    }
    if ((bl == 2 || bl == 5 || bl == 6 || bl == 7 || bl == 8) && po >= 8) {
        err = 1;return 0;
    }
    int i, j, k;
    for (i = 11;i >= 0;i--) {
        int e = 0;
        for (j = 0;j < 3;j++) {
            if(po+j>=9) break;
            for (k = 0;k < 3;k++) {
                if (tmp[po + j][i + k] == 1 && block[bl][j][k] == 1) {
                    e = 1;
                    break;
                }
            }
        }
        if (e == 1) break;
    }
    i++;
    for (j = 0;j < 3;j++) {
        if (po + j >= 9) break;
        for (k = 0;k < 3;k++) {
            if (block[bl][j][k] == 1) tmp[po + j][i + k] = 1;
        }
    }

    for (i = 0;i < 9;i++) {
        if (tmp[i][9] == 1) { err = 1;return 0; }
    }
    int height = 0,cnt=0;
    for (i = 0;i < 9;i++) {
        while (1) {
            int ch = 0;
            for (j = 0;j < 9;j++) {
                if (tmp[j][height] == 0) break;
            }
            if (j == 9) { height++; cnt++; }
            else break;
        }
        for (j = 0;j < 9;j++) tmp[j][i] = tmp[j][height];
        height++;
    }

    return cnt;
}
int calcLoss() {
    int i, j,cnt=0,cnt1=0;
    for (i = 8;i >= 0;i--) {
        for (j = 0;j < 9;j++) {
            if (tmp[j][i] == 1) break;
        }
        if (j != 9) break;
        cnt++;
    }
    for (i = 0;i < 9;i++) {
        int countt = 0;
        for (j = 8;j >= 0;j--) {
            if (tmp[i][j] == 1) countt++;
            else {
                cnt1+=countt;
            }
        }
    }
    return cnt * height - cnt1 * hard;
}
void dfs(int bl,int n) {
    int i,j,k,loss;
    if (n == 0) {
        int cnt = 0;
        err = 0;
        for (j = 0;j <= 9;j++) {
            for (k = 0;k <= 12;k++) tmp[j][k] = mapp[j][k];
        }
        for (i = 1;i <= 4;i++) {
            cnt += drop(b[bl - 1 + i], step[i]);
            if (err == 1) return;
        }
        loss = calcLoss();
        if (dp[step[1]] < loss + cnt * removeS) dp[step[1]] = loss + cnt * removeS;
        if (dp[step[1]] == 140)
            i = i;
        return;
    }
    for (i = 0;i <= 8;i++) {
        step[5-n] = i;
        dfs(bl,n - 1);
    }
}
int main() {
    int n, i,j,k;
    FILE* in = fopen("input.txt", "r");
    FILE* out = fopen("output.txt", "w");
    block[0][0][0] = 1;
    block[1][0][0] = 1;
    block[1][0][1] = 1;
    block[2][0][0] = 1;
    block[2][1][0] = 1;
    block[3][0][0] = 1;
    block[3][0][1] = 1;
    block[3][0][2] = 1;
    block[4][0][0] = 1;
    block[4][1][0] = 1;
    block[4][2][0] = 1;
    block[5][0][0] = 1;
    block[5][0][1] = 1;
    block[5][1][0] = 1;
    block[6][0][0] = 1;
    block[6][1][0] = 1;
    block[6][1][1] = 1;
    block[7][0][0] = 1;
    block[7][0][1] = 1;
    block[7][1][1] = 1;
    block[8][0][1] = 1;
    block[8][1][0] = 1;
    block[8][1][1] = 1;
    fscanf(in,"%d", &n);
    for (i = 1;i <= n;i++) {
        fscanf(in,"%d", &b[i]);
        b[i]--;
    }
    for (i = 1;i <= n;i++) {
        for (j = 0;j < 9;j++) dp[j] = -100000000;
        dfs(i,4);
        int maxx = -100000000, maxi = -1;
        for (j = 0;j < 9;j++) {
            if (maxx < dp[j]) { maxx = dp[j]; maxi = j; }
        }
        if (maxx < -50000000) {
            printf("ERR!!!!!\n");
            printf("%d", i);
            return 0;
        }
        for (j = 0;j < 9;j++) {
            for (k = 0;k < 12;k++) tmp[j][k] = mapp[j][k];
        }
        drop(b[i], maxi);
        for (j = 0;j < 9;j++) {
            for (k = 0;k < 12;k++) mapp[j][k] = tmp[j][k];
        }
        ans[i] = maxi + 1;
        if (i % 100 == 0) printf("%d\n", i);
    }
    for (i = 1;i <= 50000;i++) {
        fprintf(out, "%d\n", ans[i]);
    }
    return 0;
}

'PS - 알고리즘' 카테고리의 다른 글

14207 - 약수 도로  (0) 2024.08.19
21034 - Go To Goal  (0) 2024.08.13
4544 - 'Roid Rage  (0) 2024.08.01
27933 - 대회 이름 정하기  (0) 2024.07.25
KMP  (1) 2024.07.23