zoukankan      html  css  js  c++  java
  • BZOJ2933:POI1999地图

    Description 

       一个人口统计办公室要绘制一张地图。由于技术的原因只能使用少量的颜色。两个有相同或相近人口的区域在地图应用相同的颜色。例如一种颜色k,则A(k) 是相应的数,则有:
    • 在用颜色k的区域中至少有一半的区域的人口不大于A(k)
    • 在用颜色k的区域中至少有一半的区域的人口不小于A(k)
       区域颜色误差是该区域的人口与A(k)差的绝对值。累计误差是所有区域颜色误差的总和。我们要求出一种最佳的染色方案(累计误差最小)。
      任务
      写一个程序:
    • 读入每个区域的人口数
    • 计算最小的累计误差
    • 将结果输出

    Input

        第一行有一个整数n,表示区域数,10< n <3000。在第二行中的数m表示颜色数,2 <= m <= 10。在接下来的n中每行有一个非负整数,表示一个区域的人口。人口都不超过2^30

    Output

        输出一个整数,表示最小的累计误差

    Solution

        为了使几个区域的人口更加接近,所以先排序,然后考虑怎样将几个区域的人口分为一段,使得误差最小。又因为i号位之前的分法对于之后的分法没有影响,所以果断DP。如果用f[i][j]表示前i个区域分成j段,再去枚举这i个区域最后一段切在哪里(k),就能得到状态转移方程:f[i][j]=min(f[i][j],f[k][j-1]+(k+1到i号位的误差));

        那么就要用前缀和处理出把i到j号位分成一段的误差(1<=i<=j<=n),可离线读取。s为a的前缀和数组,那么i到j位的误差就是(mid为i到j的中位数),a[mid]*(mid-i)-(s[mid-1]-s[i-1])+(s[j]-s[mid])-a[mid]*(j-mid),画数轴自己推一下会好理解得多。

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 using namespace std;
     7 int a[3100];
     8 long long s[3100],w[3100][3100],f[3100][20];
     9 int main()
    10 {
    11     int n,m;
    12     cin>>n>>m;
    13     for (int i=1; i<=n; i++)
    14       cin>>a[i];
    15     sort(a+1,a+n+1);//先排序
    16     for (int i=1; i<=n; i++)
    17       s[i]=s[i-1]+a[i];//前缀和
    18     int mid;
    19     for (int i=1; i<=n; i++)
    20       for (int j=i; j<=n; j++)
    21       {
    22           mid=(i+j)/2;
    23           w[i][j]=a[mid]*(mid-i)-(s[mid-1]-s[i-1])+(s[j]-s[mid])-a[mid]*(j-mid);//w数组存的是区间的误差
    24       }
    25     for (int i=0; i<=n+1; i++)
    26       for(int j=0; j<=m+1; j++)
    27         f[i][j]=2100000000;
    28     f[0][0]=0;
    29     for (int i=1; i<=n; i++)
    30       for (int j=1; j<=m; j++)
    31         for (int k=0; k<=i-1; k++)
    32           f[i][j]=min(f[i][j],f[k][j-1]+w[k+1][i]);
    33     cout<<f[n][m]<<endl;
    34     return 0; 
    35 } 

    Source

        http://www.lydsy.com/JudgeOnline/problem.php?id=2933

  • 相关阅读:
    An analysis of a simple Java basic interview question: short s1=1; s1 = s1 +1 will report an error?
    <bits/stdc++.h> in C++
    linux 下配置可视化git 冲突合并工具kdiff3
    加分
    对老师的意见和课程总结
    12月19日
    12月18日
    12月17日
    12月16日
    12月15日
  • 原文地址:https://www.cnblogs.com/Patrick-X/p/6256573.html
Copyright © 2011-2022 走看看