체크수 (DP)
5019 단어 dp
Problem H:체크 수
Time Limit: 1 Sec
Memory Limit: 128 MB
Submit: 28
Solved: 9
Description
N*N 칸이 있고 칸마다 정수나 0이 있다. 가장 왼쪽 상단에서 가장 오른쪽 하단으로 가면 아래와 오른쪽만 두 번 간다. (즉 왼쪽 상단에서 오른쪽 하단으로 두 번 걷는다) 모든 칸의 수를 합쳐서 최대치인 SUM을 구하고 두 번 같은 칸을 통과하면 마지막으로 SUM에서 이 칸의 계수를 한 번만 더한다.
Input
첫 줄 N(1 <= N <= 100)
그리고 N 줄, 줄마다 N 개수.N * N 각 칸의 수치를 순서대로 나타냅니다.(0 <= value <= 1000) ;
Output
최대 SUM을 내보냅니다.
Sample Input
3
1 2 3
0 2 1
1 4 2
Sample Output
15
HINT
Hint
Possible Way:
첫 번째 1 -> 2 -> 2 -> 4 -> 2
두 번째 1 -> 2 -> 3 -> 1 -> 2
SUM = 15
아이디어:
DP.모두 두 번 걸으면 두 사람이 동시에 기점에서 종점으로 가는 것으로 볼 수 있다.점마다 위나 왼쪽에서 얻을 수 있기 때문에 두 사람이 동시에 가면 네 가지 조합이 있을 수 있다.그러므로 전이 방정식을 얻을 수 있다.
Dp [ X1 ] [ Y1 ] [ X2 ] [ Y2 ] = max (Dp [ X1 - 1 ] [ Y1 ] [ X2 - 1 ] [ Y2 ] ,
Dp [ X1 - 1 ] [ Y1 ] [ X2 ] [ Y2 - 1 ] ,
Dp [ X1 ] [ Y1 - 1 ] [ X2 - 1 ] [ Y2 ] ,
Dp [ X1 ] [ Y1 - 1 ] [ X2 ] [ Y2 - 1 ] )+ Map [ X1 ] [ Y1 ] + Map [ X2 ] [ Y2 ];
네 개의 순환, 범위가 1~100이면 시간 복잡도 O(n^4)는 TLE를 조성하기 때문에 더욱 최적화해야 한다.k로 걸음 수를 나타내면 전이 방정식은 다음과 같이 바뀔 수 있습니다.
Dp [ k ] [ X1 ] [ X2 ] = max (Dp [ k - 1 ] [ X1 - 1 ] [ X2 - 1 ] ,
Dp [ k - 1 ] [ X1 - 1 ] [ X2 ] ,
Dp [ k - 1 ] [ X1 ] [ X2 - 1 ] ,
Dp [ k - 1 ] [ X1 ] [ X2 ] ) + Map [ X1 ] [ k - X1 ] + Map [ X2 ] [ k - X2 ];
이렇게 하면 시간의 복잡도가 O(n ^ 3)로 내려가면 TLE가 발생하지 않는다.
어떻게 같은 칸을 갈 때 한 번만 추가하는 것을 피할 수 있습니까?
k는 똑같기 때문에 x1==x2일 때 y1=y2가 같은 칸을 걷기 때문에 x1==x2인지 아닌지를 판단하면 두 번을 넣을지 안 넣을지 결정할 수 있다.제목이 같은 점을 통과하지 못하도록 바뀌면 x1==x2시 continue를 사용하면 됩니다.
AC:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[210][105][105];
int Map[105][105];
int main () {
int n, sum;
scanf("%d", &n);
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
scanf("%d", &Map[i][j]);
sum = n + n - 2;
for (int k = 0; k <= sum; ++k) {
for (int x1 = 0; x1 < n; ++x1) {
for (int x2 = 0; x2 < n; ++x2) {
int ans = 0;
int y1 = k - x1, y2 = k - x2;
if (k > 0 && x1 > 0 && x2 > 0)
ans = max(ans, dp[k - 1][x1 - 1][x2 - 1]);
if (k > 0 && x1 > 0 && y2 > 0)
ans = max(ans, dp[k - 1][x1 - 1][x2]);
if (k > 0 && y1 > 0 && x2 > 0)
ans = max(ans, dp[k - 1][x1][x2 - 1]);
if (k > 0 && y1 > 0 && y2 > 0)
ans = max(ans, dp[k - 1][x1][x2]);
if (y1 < 0 || y2 < 0) continue;
dp[k][x1][x2] = ans + Map[x1][y1] +
(x1 == x2 ? 0 : Map[x2][y2]);
}
}
}
printf("%d
", dp[sum][n - 1][n - 1]);
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【경쟁 프로 전형적인 90문】008의 해설(python)의 해설 기사입니다. 해설의 이미지를 봐도 모르는 (이해력이 부족한) 것이 많이 있었으므로, 나중에 다시 풀었을 때에 확인할 수 있도록 정리했습니다. ※순차적으로, 모든 문제의 해설 기사를 들어갈 예정입니다. 문자열...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.