LetCode 제거 상자(깊이 우선 검색, 동적 계획)
:
[1, 3, 2, 2, 2, 3, 4, 3, 1]
:
23
:
[1, 3, 2, 2, 2, 3, 4, 3, 1]
----> [1, 3, 3, 4, 3, 1] (3*3=9 )
----> [1, 3, 3, 3, 1] (1*1=1 )
----> [1, 1] (3*3=9 )
----> [] (2*2=4 )
알림: 상자의 총 수는 n이 100을 넘지 않습니다.사고방식 분석: 만약에 우리가 현재 구간[i, j]을 제거해야 한다고 가정하면 boxes[i]라는 숫자를 제거하면 총 득점은 1+dp[i+1][j]이어야 한다. 그러나 제목의 요구에 따라 높은 포인트를 얻을 수 있는 사고방식은 특정한 숫자나 몇 개의 숫자를 제거한 후에 원래 연속되지 않았던 같은 숫자를 연속적으로 변화시킬 수 있기 때문이다. 동시에 제거한 숫자가 많을수록 얻은 포인트가 높기 때문이다.
그러면 [i, j] 중간에 m의 위치가 있어 boxes[i]와 boxes[m]가 같다고 가정하면 우리는 boxes[i]라는 숫자만 제거하는 것이 아니라 [i+1, m-1] 구간의 수를 직접 제거하여 boxes[i]와 boxes[m]가 직접 인접하게 하는 것도 고려해야 한다. 그러면 우리가 얻은 포인트는 dp[i+1][m-1]이다.이때 우리는 남은 boxes[i]와 boxes[m, j] 구간의 수를 처리할 수 없다. 그러나 우리는 하위 그룹 [m, j]을 처리할 수 없다. 왜냐하면 우리의 일부 정보는 우리의 dp 그룹에 포함되지 않았기 때문이다. 이런 문제는 자신이 포함하지 않는 하위 문제로 귀납되고 그 해법은 일부 하위 문제 이외의 정보에 의존한다.
이 문제에 대해 말하자면 boxes[m, j] 구간을 처리할 수 없는 것은 관건적인 정보가 부족하기 때문이다. 우리는 boxes[m] 왼쪽의 같은 숫자의 개수 k를 모른다. 이 정보를 알아야 m의 위치가 의미가 있기 때문에 우리의 dp수조는 3차원 그룹 dp[i][j][k]로 구간[i, j]에서 얻을 수 있는 최대 포인트를 나타낸다. boxes[i] 왼쪽에 k의 숫자가 있으면 그와 같다.그러면 우리의 목표는 dp[0][n-1][0]를 요구하는 것이다. 그리고 우리는 dp[i][i][k]=(1+k)*(1+k)이라는 등식을 내놓을 수 있다.
dp[i][j][k]에 대해 우리가 boxes[i]를 제거하면 (1+k)*(1+k)+dp[i+1][j][0]를 얻을 수 있다.위에서 언급한 그런 상황에 대해 어느 위치 m에 boxes[i]==boxes[m]가 있을 때 우리는 [i+1, m-1]를 먼저 제거하는 것을 고려해야 한다. 우리는 포인트 dp[i+1][m-1][0]를 얻은 다음에 나머지 부분을 처리하고 포인트 dp[m][j][k+1]를 얻는다. 여기서 k를 1점 추가한 이유는 중간 부분을 제거한 후에 원래 boxes[m]와 인접하지 않았던 boxes[i]가 지금 인접했기 때문이다. 또 양자치가 같기 때문에 k가 1을 추가해야 하기 때문이다.k의 정의는 왼쪽과 같은 숫자의 개수이기 때문이다.
class Solution {
public:
int removeBoxes(vector<int>& boxes) {
int n = boxes.size();
int dp[100][100][100] = {0};//dp[i][j][k] [i, j]( i k boxes[i] )
return helper(boxes, 0, n - 1, 0, dp);
}
// [i, j]( i k boxes[i] )
int helper(vector<int>& boxes, int i, int j, int k, int dp[100][100][100]) {
if (j < i) {//
return 0;
}
if (dp[i][j][k] > 0) {//
return dp[i][j][k];
}
// : res
// [i, j](i k boxes[i] ) [i]( k boxes[i] ) [i + 1, j](i + 1 0 boxes[i + ] )
//(1 + k) * (1 + k) boxes[i] k , helper(boxes, i + 1, j, 0, dp) [i + 1, j](i + 1 0 boxes[i + 1] )
int res = (1 + k) * (1 + k) + helper(boxes, i + 1, j, 0, dp);
// : [i + 1, j] boxes[i] , [i, j](i k boxes[i] )
for (int m = i + 1; m <= j; ++m) {
if (boxes[m] == boxes[i]) {
// [i + 1, j]
// :[i + 1, m - 1](i + 1 0 boxes[i + 1] )helper(boxes, i + 1, m - 1, 0, dp)
// : [i + 1, m - 1] boxes[i] boxes[m] , boxes[m] k + 1 helper(boxes, m, j, k + 1, dp)
res = max(res, helper(boxes, i + 1, m - 1, 0, dp) + helper(boxes, m, j, k + 1, dp));
}
}
return dp[i][j][k] = res;
}
};
다음은 위의 깊이 우선 검색법을 추이법, 즉 동적 기획법으로 수정한다.
class Solution {
public:
int removeBoxes(vector<int>& boxes) {
int n = boxes.size();
int dp[n][n][n] = {0};//dp[i][j][k] [i, j]( i k boxes[i] )
//
for (int i = 0; i < n; ++i) {
for (int k = 0; k <= i; ++k) {// i k boxes[i]
dp[i][i][k] = (1 + k) * (1 + k);
}
}
//t [i, j]
for (int t = 1; t < n; ++t) {
for (int j = t; j < n; ++j) {//
int i = j - t;//
for (int k = 0; k <= i; ++k) {
// : res
// [i, j](i k boxes[i] ) [i]( k boxes[i] ) [i + 1, j](i + 1 0 boxes[i + ] )
//(1 + k) * (1 + k) boxes[i] k , helper(boxes, i + 1, j, 0, dp) [i + 1, j](i + 1 0 boxes[i + 1] )
int res = (1 + k) * (1 + k) + dp[i + 1][j][0];
// : [i + 1, j] boxes[i] , [i, j](i k boxes[i] )
for (int m = i + 1; m <= j; ++m) {
if (boxes[m] == boxes[i]) {
// [i + 1, j]
// :[i + 1, m - 1](i + 1 0 boxes[i + 1] )helper(boxes, i + 1, m - 1, 0, dp)
// : [i + 1, m - 1] boxes[i] boxes[m] , boxes[m] k + 1 helper(boxes, m, j, k + 1, dp)
res = max(res, dp[i + 1][m - 1][0] + dp[m][j][k + 1]);
}
}
dp[i][j][k] = res;//
}
}
}
return n == 0 ? 0 : dp[0][n - 1][0];
}
};
이상의 코드는 모두 평론 구역에서 왔고, 나는 단지 주석을 추가했을 뿐이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
python 문자열 입력으로 모든 유효한 IP 주소 생성(LeetCode 93번 문제)이 문제의 공식 난이도는 Medium으로 좋아요 1296, 반대 505, 통과율 35.4%를 눌렀다.각 항목의 지표로 말하자면 보기에는 약간 규범에 맞는 것 같지만, 실제로도 확실히 그렇다.이 문제의 해법과 의도는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.