DP优化/四边形不等式
这题……跟邮局那题简直一模一样吧……好水的E题……
设dp[i][j]表示前 i 艘“gondola”坐了前 j 个人,那么方程即为$dp(i,j)=min{ dp[i-1][k]+w[k][j] } (ileq kleq j)$
很明显$w(l,r)=sum_{i=l}^r sum_{j=l}^r u(i,j) /2$是满足四边形不等式的……那么根据决策单调性直接搞就行了……
1 //CF 321E 2 #include<vector> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 using namespace std; 12 //#define debug 13 int getint(){ 14 int v=0,sign=1; char ch=getchar(); 15 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 16 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 17 return v*sign; 18 } 19 typedef long long LL; 20 const int N=100010,INF=~0u>>2; 21 /*******************tamplate********************/ 22 LL u[4001][4001],n,m,w[4001][4001],dp[801][4001]; 23 int s[801][4001]; 24 int main(){ 25 #ifndef ONLINE_JUDGE 26 freopen("input.txt","r",stdin); 27 // freopen("output.txt","w",stdout); 28 #endif 29 n=getint(); m=getint(); 30 F(i,1,n) F(j,1,n) u[i][j]=getint(); 31 F(i,1,n) F(j,1,n) u[i][j]+=u[i-1][j]+u[i][j-1]-u[i-1][j-1]; 32 33 F(i,1,n) F(j,i+1,n) w[i][j]=u[j][j]-u[i-1][j]-u[j][i-1]+u[i-1][i-1]; 34 35 #ifdef debug 36 F(i,1,n) {F(j,1,n) printf("%3d",w[i][j]);puts("");} 37 #endif 38 F(i,1,m) F(j,1,n) dp[i][j]=INF; 39 F(i,1,n){ 40 dp[1][i]=w[1][i]; 41 s[1][i]=0; 42 } 43 F(i,2,m){ 44 s[i][n+1]=n; 45 D(j,n,i) 46 F(k,s[i-1][j],s[i][j+1]) 47 if (dp[i-1][k]+w[k+1][j]<dp[i][j]){ 48 s[i][j]=k; 49 dp[i][j]=dp[i-1][k]+w[k+1][j]; 50 } 51 } 52 printf("%I64d ",dp[m][n]/2); 53 return 0; 54 }