bzoj 1084 DP
8118 단어 ZOJ
그러면 이동도 비교적 뚜렷하다. 몇 가지 이동이 있다
w[i][j][k]=max(w[i-1][j][k], w[i][j-1][k]) 이런 상황은 아무것도 선택하지 않는 것을 대표한다.
l[i][j][k]=max(w[ii][j][k-1]+sum[ii+1][i][0]) 이런 상황은 왼쪽 줄에서 i의 위치를 어떻게 선택하는지 다시 확인하는 것을 의미한다.
유사한 w[i][j][k]=max(w[i][jj][k-1]+sum[jj+1][j][1]) 이런 상황은 오른쪽 줄에서 i라는 위치를 어떻게 선택하는지 다시 확인하는 것을 의미한다.
i==j일 때 w[i][j]=max(w[ii][ii]+sum[ii+1][i][2])를 선택하면 두 줄을 차지하는 직사각형을 선택한 다음에 매거된 경계를 주의하면 된다.
반성: 처음에 나의 생각은 w[i][k]가 두 줄 행렬을 대표하기 전에 i개의 k개 행렬의 최대치를 선택한 것이다. 우리는 행렬을 선택하는 방법이 한 줄만 선택한 조합이 틀림없다는 것을 알 수 있다. 그리고 두 줄을 선택한 다음에 분리된다. 그러면 우리는 i가 두 줄을 차지하는 사각형(이 행렬의 길이는 0이 될 수 있다)을 일일이 열거할 수 있다. 그러면 w[i][k]=max(w[j][k]+f[j+1][ii]+sum[ii][ii]]]]][ii]]]]를 대표한다.이 이동은 먼저 한 번의 단점을 열거한 다음에 한 개의 단점을 i로 열거하는 경우이다. 한 줄만 선택한 다음에 한 줄이 두 줄의 최대치를 차지한다. 그러면 먼저 한 줄의 f[i][j][k]값을 처리해야 한다. 이것은 i를 대표하고 j단은 k개 행렬의 최대치를 선택한다.나중에 이동할 때 매거 경계가 너무 번거로워서 조정하지 못했다. 다시 생각해 보니 이런 이동은 상태수가 너무 적어서 모든 상태를 정확하게 표현할 수 없기 때문에 옮기는 것이 매우 번거롭다. 그래서 1차원을 더하면 모든 상태를 정확하게 표현할 수 있고 옮기는 것이 매우 편리하다. 복잡도도 k(지난 방법은 좌우 두 줄을 매거하여 몇 개의 직사각형을 선택해야 하기 때문이다).어쨌든 내가 너무 약해서...
/**************************************************************
Problem: 1084
User: BLADEVIL
Language: C++
Result: Accepted
Time:88 ms
Memory:1672 kb
****************************************************************/
//By BLADEVIL
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100
#define maxm 20
using namespace std;
int n,m,k;
int a[maxn][maxn],sum[maxn][maxn],f[maxn][maxm],w[maxn][maxn][maxm];
int main(){
scanf("%d%d%d",&n,&m,&k);
sum[0][1]=sum[0][2]=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&a[i][j]),sum[i][j]=sum[i-1][j]+a[i][j];
if (m==1){
memset(f,0,sizeof(f));
for (int i=1;i<=n;i++) {
f[i][0]=0;
for (int l=1;l<=k;l++){
f[i][l]=f[i-1][l];
for (int j=0;j<i;j++){
f[i][l]=max(f[i][l],f[j][l-1]+sum[i][1]-sum[j][1]);
}
}
}
printf("%d
",f[n][k]);
} else {
memset(w,0,sizeof(w));
for (int i=1;i<=n;i++) {
for (int j=1;j<=n;j++){
w[i][j][0]=0;
for (int l=1;l<=k;l++){
w[i][j][l]=max(w[i-1][j][l],w[i][j-1][l]);
for (int ii=0;ii<i;ii++)
w[i][j][l]=max(w[i][j][l],w[ii][j][l-1]+sum[i][1]-sum[ii][1]);
for (int jj=0;jj<j;jj++)
w[i][j][l]=max(w[i][j][l],w[i][jj][l-1]+sum[j][2]-sum[jj][2]);
if (i==j)
for (int jj=0;jj<i;jj++)
w[i][i][l]=max(w[i][i][l],w[jj][jj][l-1]+sum[i][1]-sum[jj][1]+sum[j][2]-sum[jj][2]);
}
}
}
printf("%d
",w[n][n][k]);
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
수학법칙을 찾으면 돼요. 그다음에 정답은요. k^(m-1)*(n-(m-1)*k)+(m+(m-1)*k+1)*k^(m-1) div 2...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.