전공/알고리즘
백준 2186(문자판)
xkdlaldfjtnl
2020. 10. 25. 17:06
2186번: 문자판
첫째 줄에 N(1 ≤ N ≤ 100), M(1 ≤ M ≤ 100), K(1 ≤ K ≤ 5)가 주어진다. 다음 N개의 줄에는 M개의 알파벳 대문자가 주어지는데, 이는 N×M 크기의 문자판을 나타낸다. 다음 줄에는 1자 이상 80자 이하의
www.acmicpc.net
좀 전형적인 dp문제인것 같다.
그냥 점화식 자체가 그래프 + dp를 하게되면 top-down으로 기저조건 잘 넣고 [][][]이런식으로 몇번째 몇번째 칸을 몇번째 순서로 들어갈지 이런식으로 코드를 짜면 된다.
여기서 dp[i][j][num] 에는 마지막에서 (i,j)로 돌아왔을때 경우의 수가 저장된다.
설명이 이상한데 그냥 점화식을 쓰면
dp[i][j][num] += 모든 num+1의 ni,nj에 대해서 dp[ni][nj][num+1] 이된다.
기저 조건을 잘 넣고 하면 그냥 끝
#include<iostream>
#include<string>
#include<queue>
#include<utility>
#include<cstring>
using namespace std;
#define MAX 105
queue<pair<int, int> > q;
string s;
int N, M, K;
int dx[4] = { 1,-1,0,0 };
int dy[4] = { 0,0,1,-1 };
int dp[MAX][MAX][MAX];
char mat[MAX][MAX];
int solve(int x, int y, int now) {
if (now == s.size() - 1)return 1;
int &ret = dp[x][y][now];
if (ret!=-1)return ret;
ret = 0;
for (int i = 1; i <= K; i++) {
for (int j = 0; j < 4; j++) {
int nx = x + i * dx[j];
int ny = y + i * dy[j];
if (nx<0 || ny <0 || nx>N || ny > M)continue;
if (mat[nx][ny] == s.at(now+1)) {
ret+=solve(nx,ny,now+1);
}
}
}
return ret;
}
int main() {
memset(dp, -1, sizeof(dp));
cin >> N >> M >> K;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
char a;
cin >> a;
mat[i][j] = a;
}
}
cin >> s;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (mat[i][j] == s.at(0)) {
q.push(make_pair(i, j));
}
}
}
int ans = 0;
while (!q.empty()) {
pair<int, int> p = q.front();
q.pop();
ans+=solve(p.first, p.second, 0);
}
cout << ans;
}