zoukankan      html  css  js  c++  java
  • 山区建小学(OJ 7624)

    描述

    政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往。已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i < m。为了提高山区的文化素质,政府又决定从m个村中选择n个村建小学(设 0 < n < = m < 500 )。请根据给定的m、n以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值。

    输入

    第1行为m和n,其间用空格间隔
    第2行为(m-1) 个整数,依次表示从一端到另一端的相邻村庄的距离,整数之间以空格间隔。

    例如
    10 3
    2 4 6 5 2 4 3 1 3
    表示在10个村庄建3所学校。第1个村庄与第2个村庄距离为2,第2个村庄与第3个村庄距离为4,第3个村庄与第4个村庄距离为6,...,第9个村庄到第10个村庄的距离为3。

    输出

    各村庄到最近学校的距离之和的最小值。

    样例输入

    10 2
    3 1 3 1 1 1 1 1 3

    样例输出

    18

    仍在Xing学长的帮助下完成了该题-QWQ

    解析:

    本题关键在于起始的预处理,将各个村庄的位置像数轴一样表示在pos数组里

    再开一个arr[ i ][ j ] 表示 i~j 村庄必要走的路线长度(可以看成i~j村庄到 1 个小学的最短路程总和)

    那么DP就容易啦

     

    代码 ^-^:

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int arr[1001][1001],pos[1001],f[1001][1001];
    
    int main()
    {
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=2;i<=n;++i) {
            scanf("%d",&pos[i]);
            pos[i]+=pos[i-1];
        }
        for(int i=1;i<n;++i)
        {
            for(int j=i+1;j<=n;++j)    {
                arr[i][j]=arr[i][j-1]+pos[j]-pos[(i+j)>>1];
            }
        }
        memset(f,13,sizeof(f));
        for(int i=1;i<=n;++i)
            f[i][1]=arr[1][i];
            
        for(int i=2;i<=n;++i)
            for(int j=2;j<=k&&j<=i;++j)
                for(int q=j-1;q<i;++q){
                    f[i][j]=min(f[i][j],f[q][j-1]+arr[q+1][i]);
                }
        printf("%d",f[n][k]);
        return 0;        
    }

    updated:2018-10-24

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int arr[1001][1001],pos[1001],f[1001][1001];
    
    int main()
    {
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=2;i<=n;++i) {
            scanf("%d",&pos[i]);
            pos[i]+=pos[i-1];
        }
        for(int i=1;i<n;++i)
        {
            for(int j=i+1;j<=n;++j) {
                arr[i][j]=arr[i][j-1]+pos[j]-pos[(i+j)>>1];
            }
        }
        memset(f,13,sizeof(f));
        for(int i=1;i<=n;++i)
            f[i][1]=arr[1][i]; //前 i 个村庄建 1 所小学 
            
        for(int i=2;i<=n;++i) //前 i 个村庄 
            for(int j=2;j<=k&&j<=i;++j) //建 j 所小学 
                for(int q=j-1;q<i;++q) { //前 q 个村庄分配 j-1 所小学 
                    f[i][j]=min(f[i][j],f[q][j-1]+arr[q+1][i]);
                }
        printf("%d",f[n][k]);
        return 0;        
    }
    从0到1很难,但从1到100很容易
  • 相关阅读:
    PDIUSBD12指令
    (转)USB的VID和PID,以及分类(Class,SubClass,Protocol)
    静态测试
    一种循环buffer结构
    RL78 芯片复位指令
    XModem协议
    位反转的最佳算法
    CCP 协议
    AUTOSAR 架构
    HEX 文件格式
  • 原文地址:https://www.cnblogs.com/qseer/p/9436428.html
Copyright © 2011-2022 走看看