BZOJ1575: [Usaco2009 Jan]气象牛Baric
n<=100个数字,选最少的个数使“误差”少于E并输出选该个数下最小的“误差”。误差定义:
对于任何测量结果子集,每一个非此子集中的结果都会产生误差.总误差是所有测量结果的误差之和.更明确第说, 对于每一个和所有s_j都不同的i: * 如果 i 小于 s_1, 误差是: 2 * | M_i - M_(s_1) | * 如果i在s_j和s_(j+1)之间,误差是: | 2 * M_i - Sum(s_j, s_(j+1)) | 注:Sum(x, y) = M_x + M_y; (M_x 和 M_y 之和) * 如果i大于s_K,误差为: 2 * | M_i - M_(s_K) |
n很小,来dp吧!f[i][j]--前i个数,最后选i,共选j个最小误差,f[i][j]=f[k][j-1]-k到n对k的误差+k到i对(k,i)的误差+i到n对i的误差。
n^4,那坨长长的怎么破?预处理啦!变n^3。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<math.h> 5 //#include<iostream> 6 using namespace std; 7 8 int n,E; 9 #define maxn 111 10 int suf[maxn],pre[maxn],med[maxn][maxn],f[maxn][maxn],a[maxn]; 11 const int inf=0x3f3f3f3f; 12 int main() 13 { 14 scanf("%d%d",&n,&E); 15 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 16 for (int i=1;i<=n;i++) 17 { 18 pre[i]=0; 19 for (int j=1;j<i;j++) 20 pre[i]+=2*fabs(a[j]-a[i]); 21 } 22 for (int i=n;i>=1;i--) 23 { 24 suf[i]=0; 25 for (int j=i+1;j<=n;j++) 26 suf[i]+=2*fabs(a[j]-a[i]); 27 } 28 for (int i=1;i<=n;i++) 29 for (int j=i;j<=n;j++) 30 { 31 med[i][j]=0; 32 for (int k=i+1;k<j;k++) 33 med[i][j]+=fabs(2*a[k]-a[i]-a[j]); 34 } 35 int ans=0,lest=inf; 36 for (int i=1;i<=n;i++) 37 { 38 f[i][1]=pre[i]+suf[i]; 39 if (f[i][1]<=E) {ans=1;lest=min(lest,f[i][1]);} 40 } 41 for (int j=2;!ans && j<=n;j++) 42 for (int i=1;i<=n;i++) 43 { 44 f[i][j]=inf; 45 for (int k=1;k<i;k++) 46 f[i][j]=min(f[i][j],f[k][j-1]-suf[k]+suf[i]+med[k][i]); 47 if (f[i][j]<=E) {ans=j;lest=min(lest,f[i][j]);} 48 } 49 printf("%d %d\n",ans,lest); 50 return 0; 51 }