[6w] 시뮬레이션

hwee·2024년 8월 14일
0

algo_study_2024

목록 보기
6/7

시뮬레이션이란? : reference
코드트리 : 왕실의 기사
아이디어



코드

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <queue>
using namespace std;
#define MAX_L 41

//전역변수
int L,N,Q;
struct Knight{
    int r,c,h,w,k;
    int damage=0; //받은 데미지
    int damageSum=0; //누적 데미지
    bool isMove=false;
    int knightNum;
};

int chess[MAX_L][MAX_L];
vector<Knight> knightV;
vector<int> moveY={-1, 0, 1, 0};   //상우하좌  
vector<int> moveX={0, 1, 0, -1};
vector<pair<int, int>> order;  //first : 기사 id second : 이동방향
int result=0;
//전역변수 종료

bool simulation(int knightNum, int direction, int aa){
    for(int i=1;i<=N;i++){  //기사들의 이번턴 변수 초기화
        knightV[i].damage=0;
        knightV[i].isMove=false;
    }
    Knight nowKnight=knightV[knightNum];
    knightV[nowKnight.knightNum].isMove=true;  //첫기사는 움직인거 처리 미리해줌
    nowKnight.isMove=true;
    queue<Knight> q;
    q.push(nowKnight);
    while(!q.empty()){
        nowKnight=q.front(); q.pop(); //한놈씩 뽑아서
        nowKnight.r+=moveY[direction];
        nowKnight.c+=moveX[direction];
        if(nowKnight.r<1||nowKnight.r+nowKnight.h-1>L||nowKnight.c<1||nowKnight.c+nowKnight.w-1>L)
            return false;
        //기사가 체스판 밖으로 나감
        for(int i=nowKnight.r;i<nowKnight.r+nowKnight.h;i++){  //기사의 방패 범위 돌아보기
            for(int j=nowKnight.c;j<nowKnight.c+nowKnight.w;j++){
                if(chess[i][j]==2) return false; //기사가 벽에 부딪힘
                if(chess[i][j]==1){
                    //기사가 폭탄 밟으면
                    knightV[nowKnight.knightNum].damage++;
                    //cout<<aa<<"번명령: "<<nowKnight.knightNum<<"번기사 폭탄밟음"<<i<<", "<<j<<"에서\n";
                }
            }
        }
        for(int i=1;i<=N;i++){
            if(knightV[i].r>nowKnight.r+nowKnight.h-1||knightV[i].r+knightV[i].h-1<nowKnight.r) continue;
            if(knightV[i].c>nowKnight.c+nowKnight.w-1||knightV[i].c+knightV[i].w-1<nowKnight.c) continue;
            if(knightV[i].isMove||knightV[i].k<=0) continue;            
            knightV[i].isMove=true;
            q.push(knightV[i]);
        }
    }
    return true;
}

void getOrder(int knightNum, int direction, int aa){  //첫 명령 수행 함수
    Knight knight=knightV[knightNum];
    if(knight.k<=0) return;  //현재 기사 죽었으면 수행 X
    if(simulation(knightNum, direction, aa)){  //현재 기사 포함 연결된 전체 기사 움직일 수 있으면
        //cout<<aa<<"번째 명령 수행성공\n";
        for(int i=1;i<=N;i++){  
            if(knightV[i].isMove){    //이번턴에 움직인 기사들 정산  
                if(i!=knightNum){  //첫기사 예외처리
                    knightV[i].k-=knightV[i].damage; 
                    knightV[i].damageSum+=knightV[i].damage;
                }
                knightV[i].r+=moveY[direction];
                knightV[i].c+=moveX[direction];
            }
        }
    }
}

int main() {
    cin>>L>>N>>Q;
    for(int i=1;i<=L;i++){  //체스판 초기화
        for(int j=1;j<=L;j++){
            cin>>chess[i][j];
        }
    }
    Knight trashKnight;
    knightV.push_back(trashKnight); //0번기사 넣어두기
    for(int i=1;i<=N;i++){ //기사정보 초기화
        Knight addKnight;
        cin>>addKnight.r>>addKnight.c>>addKnight.h>>addKnight.w>>addKnight.k;
        addKnight.knightNum=i;
        knightV.push_back(addKnight);
    } 
    for(int i=0;i<Q;i++) {  //명령 수행
        int a,b;
        cin>>a>>b;
        getOrder(a,b,i+1);
    }
    for(int i=1;i<=N;i++){
        if(knightV[i].k>0) {
            result+=knightV[i].damageSum;
        }
    }
    cout<<result;
    return 0;
}
profile
화이팅!

0개의 댓글