vijos圆环取数(好题,我不会,来日再补)

来源:互联网 发布:基金开户数据 编辑:程序博客网 时间:2024/05/22 16:58
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2010;
int n,k,a[2*maxn],f[2*maxn][20],dp[maxn][maxn][2];
int rmq(int l,int r){
 if(l>r) return 0;
    int i=0;
    for(;(1<<i)+l-1<=r;i++){};
    i--;
    return min(f[l][i],f[r-(1<<i)+1][i]);
}
int main(){
 scanf("%d%d",&n,&k);
 for(int i=1;i<=n;i++) scanf("%d",&a[i]);
 int m=n;
 for(int i=1;i<=m;i++)
        f[i][0]=a[i];
    for(int j=1;(1<<j)<m;j++){
        for(int i=1;i<=m;i++){
            if(i+(1<<j)-1<=m){
                f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
            }
        }
    }
 memset(dp,0x7f,sizeof(dp));
 /*for(int k=1;k<=n-k;k++){
  for(int i=1;i<=m-k;i++){
   int j=i+k;
   int now=100000000; if(j!=m) now=rmq(j+1,m);
   int now1=100000000; if(i!=1) now1=rmq(1,i-1);
   /*dp[i][j]=min(dp[i][j],dp[i+1][j]+a[i]+min(rmq(1,i),now));
   dp[i][j]=min(dp[i][j],dp[i][j-1]+a[j]+min(rmq(j,2*n-1),now1));
   dp[i][j]=min(dp[i][j],dp[i][j]+min(now1,now));
  }
 }*/
 for(int i=0;i<=n;i++){
  for(int j=0;j<=n-i;j++){
   if(i==0&&j==0) continue;
   int now=rmq(2+i+k,n-k-j+1);
   if(j>0) dp[i][j][1]=min(dp[i][j-1][1]+now,dp[i][j-1][0]+
   (i+j)*now);
   else dp[i][j][1]=100000000;
   now=rmq(1+i+k,n-k+j);
   if(i>0){
    dp[i][j][0]=min(dp[i+1][j][0]+now,dp[i][j-1][1]+(i+j)
    *now);
   }
   else dp[i][j][0]=100000000;
  }
 }
 int ans=100000000,s=0;
 for(int i=0;i<=n;i++){
  ans=min(ans,min(dp[i][n-i][0],dp[i][n-i][1]));
 }
 for(int i=1;i<=n;i++) s+=a[i];
 cout<<ans+s<<endl;
 return 0;
}
原创粉丝点击