Ciel and Gondolas
动态规划方程是dp[i][j]=min{dp[i-1][j]+cal(k+1,j)},cal(i,j)=cal(i-1,j)+cal(i,j-1)-cal(i-1,i-1)+ch[j][j]。做题时,没有注意策略点的范围,超时了好几次。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<fstream>
using namespace std;
const int maxn=5e3+5;
int dp[maxn][maxn];
int gf[maxn][maxn];
int ch[maxn][maxn],n,k;
int getK(int i,int j,int k)
{
return dp[i-1][k]+gf[j][j]-gf[k][j]-gf[j][k]+gf[k][k];
}
void solve(int L,int R,int l,int r,int i)
{
if(L>R)
return ;
int mid=(L+R)>>1;
int ans=0x3f3f3f3f,index=0;
for(int j=l; j<=min(mid,r); j++)
{
if(ans>getK(i,mid,j))
{
ans=getK(i,mid,j);
index=j;
}
}
dp[i][mid]=ans;
solve(L,mid-1,l,index,i);
solve(mid+1,R,index,r,i);
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
scanf("%d",&ch[i][j]);
gf[i][j]=gf[i-1][j]+gf[i][j-1]+ch[i][j]-gf[i-1][j-1];
}
for(int i=1;i<=n;i++)dp[0][i]=0x3f3f3f3f;
dp[0][0]=0;
for(int i=1; i<k; i++)
{
solve(1,n,0,n,i);
}
int ans=0x3f3f3f3f;
for(int i=0; i<=n; i++)
{
if(ans>getK(k,n,i))
{
ans=getK(k,n,i);
}
}
printf("%d",ans/2);
}