zoukankan      html  css  js  c++  java
  • 建学校

    总时间限制: 
    1000ms 
    内存限制: 
    65536kB
    描述

    政府在某山区修建了一条道路,恰好穿越总共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



    代码:

    java:

    import java.util.Scanner;
    
    public class BuildSchool {
    	public static void main(String[] args) {
    		Scanner sc = new Scanner(System.in);
    		int m = sc.nextInt();
    		int n = sc.nextInt();
    		int a[] = new int[m+1];//存放从第一个村庄到其它m-1个村庄的距离
    		int b[][] = new int[m+1][m+1];//存放从第i个村庄到第j个村庄的距离
    		int s[][] = new int[m+1][m+1];//存放从第i个村庄到第j个村庄里区间内村庄到学校的距离和
    		int f[][] = new int[m+1][m+1];//存放从第i个村庄到第j个村庄题目要求的距离
    		
    		for (int i = 2; i < a.length; i++) {
    			a[i] = sc.nextInt();
    			a[i] = a[i-1] + a[i];
    		}
    
    		for (int i = 1; i < b.length; i++) {
    			for (int j = 1; j < b[i].length; j++) {
    				if(i<=j) b[i][j] = a[j] -a[i];
    				else b[i][j] = a[i] - a[j];
    //				System.out.print(b[i][j]+" ");
    			}
    //			System.out.println();
    		}
    
    		for (int i = 1; i < s.length; i++) {
    			for (int j = i; j < s[i].length; j++) {
    				if(i==j) s[i][j] = 0;
    				else s[i][j] = dist(i,j,b);
    //				System.out.print(s[i][j]+" ");
    			}
    //			System.out.println();
    		}
    
    		for (int i = 1; i < f.length; i++) {
    			for (int j = 1; j < f[i].length; j++) {
    				f[i][j] = Integer.MAX_VALUE;
    			}
    			for (int j = 1; j < f.length; j++) {
    				f[j][j] = 0;
    				f[j][1] = s[1][j];
    			}
    		}
    		for (int i = 2; i <= m; i++) {//核心算法
    			for (int j = 2; j <= min(i,n); j++) {
    				for (int k = j-1; k <= i-1; k++) {
    					if(i!=j) f[i][j] = min(f[i][j],f[k][j-1]+s[k+1][i]);
    				}	
    			}
    		}
    //		for (int i = 1; i < f.length; i++) {
    //			for (int j = 1; j < f[i].length; j++) {
    //				System.out.print(f[i][j]+" ");
    //			}
    //			System.out.println();
    //		}
    		System.out.println(f[m][n]);
    	}
    
    	private static int min(int i, int j) {
    		if(i<=j) return i;
    		return j;
    	}
    
    	private static int dist(int i, int j, int b[][]) {
    		int mid = (i+j)/2;
    		int max = 0;
    		for (int k = i; k <= j; k++) {
    			max += b[k][mid];
    //			System.out.print(b[i][mid]+"kkkkkk");
    		}
    		return max;
    	}
    }
    

    C:

    #include<iostream>  
    #include<cstdio>  
    #include<algorithm>  
    #include<cmath>  
    using namespace std;  
    const int inf=99999999;  
    int f[510][510];  
    int dis[510][510];//从i到j距离   
    int d[510];  
    int s[510][510];  
    //s[管辖区起点][管辖区终点]=这片辖区内建一个学校,区内村庄到学校的距离和  
    int n,m;  
    int dist(int i,int j){  
        int x=0;  
        int mid=(i+j)/2;  
        for(int k=i;k<=j;k++)  
          x+=dis[k][mid];  
        return x;  
    }  
      
    int main(){  
        scanf("%d%d",&m,&n);  
        int i,j,x;  
        for(i=2;i<=m;i++){//从2开始,方便求各村庄间距离  
            scanf("%d",&x);  
            d[i]=d[i-1]+x;  
        }  
        //  
        for(i=1;i<=m;i++)  
          for(j=1;j<=m;j++){  
            if(i==j)dis[i][j]=0;  
            else dis[i][j]=dis[j][i]=abs(d[j]-d[i]);  
          }//初始化两两距离   
        //  
        for(i=1;i<=m;i++)  
          for(j=1;j<=m;j++)  
            s[i][j]=dist(i,j);  
        //计算一个管辖从i到j村庄的学校到这些村庄的距离和  
        //  
        for(i=1;i<=m;i++)  
          for(j=1;j<=m;j++)  
            f[i][j]=inf;  
        for(i=1;i<=m;i++)f[i][i]=0;  
        for(i=1;i<=m;i++)f[i][1]=s[1][i];//只建一个学校的情况   
        //f初始化   
              
    /*  //test 
        for(i=1;i<=m;i++) 
          for(j=1;j<=m;j++) 
            printf("%d ",s[i][j]);     
    */    
        for(i=2;i<=m;i++){//村庄  
            for(j=2;j<=min(i,n);j++){//学校   
                for(int k=j-1;k<=i-1;k++){//枚举已有的学校管辖的范围   
                    if(i!=j)f[i][j]=min(f[i][j],f[k][j-1]+s[k+1][i]);  
                }     
            }   
        }  
        printf("%d",f[m][n]);  
          
    }












  • 相关阅读:
    jQuery EasyUI API 中文文档 数字框(NumberBox)
    jQuery EasyUI API 中文文档 数值微调器(NumberSpinner)
    jQuery EasyUI API 中文文档 日期时间框(DateTimeBox)
    jQuery EasyUI API 中文文档 微调器(Spinner)
    jQuery EasyUI API 中文文档 树表格(TreeGrid)
    jQuery EasyUI API 中文文档 树(Tree)
    jQuery EasyUI API 中文文档 属性表格(PropertyGrid)
    EntityFramework 数据操作
    jQuery EasyUI API 中文文档 对话框(Dialog)
    jQuery EasyUI API 中文文档 组合表格(ComboGrid)
  • 原文地址:https://www.cnblogs.com/-rainbow-/p/8361555.html
Copyright © 2011-2022 走看看