Notice
Recent Posts
Recent Comments
Link
«   2026/06   »
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
Archives
Today
Total
관리 메뉴

dh-winternagi 님의 블로그

(1657) 두부장수 장홍준 본문

백준 (C++)/Solve

(1657) 두부장수 장홍준

dh-winternagi 2026. 4. 27. 00:08

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

단계별로 풀어보기

50단계(동적 계획법 4) 7번째

 

 

 

브로큰 프로파일 DP를 이용해 풀면 된다. 어떤 칸에서 다음 단계로 나아가는 경우의 수는 이번 칸 무시, 가능하다면 가로로 자르기와 세로로 자르기 3가지가 있고 가로로 자를 때와 세로로 자를 땐 잘린 두부의 금액만큼 더해주면 된다. 이제 세 경우 중 최대값을 구하면 된다.

 

 

 

#include <iostream>
#include <vector>
using namespace std;
#define INF 1000

int main() {
  int n, m, ans= 0;

  cin >> n >> m;
  
  vector<vector<int>> cost={{10,8,7,5,1},{8,6,4,3,1},{7,4,3,2,1},{5,3,2,2,1},{1,1,1,1,0}};
  vector dp(n*m, vector<int> (1<<m, -1)), v(n, vector<int> (m));
  
  for(int i=0;i<n;i++){
    string s;

    cin >> s;

    for(int j=0;j<m;j++){
      if(s[j]=='A')  v[i][j]= 0;
      else if(s[j]=='B')  v[i][j]= 1;
      else if(s[j]=='C')  v[i][j]= 2;
      else if(s[j]=='D')  v[i][j]= 3;
      else  v[i][j]= 4;
    }
  }

  auto func= [&](auto self, int now, int state) -> int {
    if(now==n*m && !state)  return 0;
    if(now>=n*m)  return -INF;
    
    int& ret= dp[now][state];
    
    if(ret!=-1)  return ret;
    
    int x= now/m, y= now%m;
    
    ret= 0;
    
    ret= max(ret, self(self, now+1, state>>1));
    
    if(!(state&1)){
      if(x!=n-1){
        ret= max(ret, cost[v[x][y]][v[x+1][y]]+self(self, now+1, (state>>1)|(1<<(m-1))));
      }
      if(y!=m-1 && !(state&2)){
        ret= max(ret, cost[v[x][y]][v[x][y+1]]+self(self, now+2, (state>>2)));
      }
    }
    
    return ret;
  };
  
  cout << func(func, 0, 0);
  
  return 0;
}

'백준 (C++) > Solve' 카테고리의 다른 글

(13448) SW 역량 테스트  (0) 2026.04.27
(2315) 가로등 끄기  (0) 2026.04.27
(1648) 격자판 채우기  (0) 2026.04.26
(13976) 타일 채우기 2  (0) 2026.04.26
(2494) 숫자 맞추기  (0) 2026.04.26