標籤:
一個劃分dp,不過由於劃分個數任意,僅用一維數組就可以
設dp[i]表示前i個裝箱(任意個箱子)的費用最小值
dp[i]=min(dp[u]+cost(u+1,i))
但是n<=50000,n方的複雜度顯然不能接受
設choice[i]數組存下對於每個i值,枚舉所得的使f[i]最大的那個u值
打表,發現choice[]是單調不下降的
則每次對於一個新的i,在枚舉u時只需要從choice[i-1]開始即可
代碼:
#include<iostream>#include<cstring>#define Size 50005using namespace std;int n;int c[Size];long long sum[Size];long long L;long long dp[Size];int choice[Size];long long cost(int l,int r){ long long x=sum[r]-sum[l-1] + r-l; return (x-L)*(x-L);}int main(){ freopen("1319.in","r",stdin); memset(dp,0x7f,sizeof(dp)); cin>>n>>L; for(int i=1;i<=n;i++){ cin>>c[i]; sum[i]=sum[i-1]+c[i]; } dp[0]=0; choice[0]=0; for(int i=1;i<=n;i++){ for(int u=choice[i-1];u<=i-1;u++){ if(dp[u]+cost(u+1,i)<=dp[i]){ dp[i]=dp[u]+cost(u+1,i); choice[i]=u; } } } cout<<dp[n]; fclose(stdin); return 0;}
至於更好的nlgn的二分最佳化和n的斜率最佳化,改天再說吧...sleeping
code1319 玩具裝箱