`
Eastsun
  • 浏览: 311181 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

《程序员》2007第八期之算法擂台

阅读更多
题目描述(手头没书,不知道有没有记错):有v个在一条直线上的村庄,要在其中的p个村庄上修建邮局。每个村庄将会选择离其最近的村庄收发邮件。现在要选择这p个邮局的修建地址,使得这v个村庄到邮局的总路程尽可能少。
输入:首先是两个正整数v,p,表示村庄个数与邮局个数。
      然后是v个不小于零的整数,表示v个村庄的坐标。
输出:p从小到大个用空格分开的整数,表示p个邮局的坐标。



这个题目用简单的重举法显然是行不通的,那样时间复杂度将达到阶乘级别。
我用的是动态规划,时间复杂度为O(n*n*(n+p)).不知道有没有更好的算法。

注意:这个题目的解实际上不唯一,比如v=2,p=1的情形,邮局修在村庄1与村庄2是一样的。[/color]
/**
 * &#Postoffice.java
 * 算法描述:
 *     记m(i,j)为前i个村庄设置j个邮局时最小的总路程,
 *     s(i,j)为从村庄i到j中(包括i,j)中设置一个村庄时需要的最小路程,则有:
 *     m(i,j) =min{ m(k,j-1)+s(k,i-1) : j-1<=k<=i-1}
 * 则状态总数为 O(n*(p+n)),转移代价为O(n),故总体时间复杂度为O(n*n*(n+p))
 * @author Eastsun
 * @version 2.0 2008/8/27
 */
package eastsun.algorithm;

import java.util.*;

public class Postoffice {

    private Postoffice() {
    }

    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        int v = s.nextInt();
        int p = s.nextInt();
        int[] villages = new int[v];
        for (int index = 0; index < v; index++) {
            villages[index] = s.nextInt();
        }
        for (int post : solve(villages, p)) {
            System.out.println(post + " ");
        }
    }

    /**
     * 求解
     * @param villages 村庄坐标
     * @param p        邮局个数
     * @return postoffices 按升序排列的邮局坐标
     */
    public static int[] solve(int[] villages, int p) {
        Arrays.sort(villages);
        int v = villages.length;

        //对于p<=2时,特殊处理
        if (p <= 2) {
            return solveX(villages, p);
        }

        //simple[i][j] 表示从村庄i到j(包括i,j)中放置一个邮局时这些村庄要走的路程
        int[][] simple = new int[v][v];
        for (int i = 0; i < v; i++) {
            for (int j = i; j < v; j++) {
                //此时,将邮局修在中间那个村庄可以得到最小路程
                int pos = (i + j) / 2;
                for (int k = i; k <= j; k++) {
                    simple[i][j] += k <= pos ? villages[pos] - villages[k] : villages[k] - villages[pos];
                }
            }
        }

        //min[i][j] 表示在villages[0...i-1]中修建j个邮局时最小的路程
        int[][] min = new int[v + 1][p + 1];
        //trace[i][j] 表示这j个邮局中最后一个邮局影响村庄的起始位置
        int[][] trace = new int[v + 1][p + 1];
        for (int i = 1; i <= v; i++) {
            min[i][1] = simple[0][i - 1];
        }
        for (int j = 2; j <= p; j++) {
            for (int i = j; i <= v; i++) {
                min[i][j] = Integer.MAX_VALUE;
                for (int k = j - 1; k <= i - 1; k++) {
                    if (min[i][j] > min[k][j - 1] + simple[k][i - 1]) {
                        min[i][j] = min[k][j - 1] + simple[k][i - 1];
                        trace[i][j] = k;
                    }
                }
            }
        }
        int[] postoffices = new int[p];
        int end = v - 1;
        for (int index = p - 1; index >= 0; index--) {
            int begin = trace[end + 1][index + 1];
            postoffices[index] = villages[(begin + end) / 2];
            end = begin - 1;
        }
        return postoffices;
    }

    /**
     * 对邮局个数为1或2时的处理
     * 此时对应的时间复杂度为O(1) 与O(n*n)
     */
    private static int[] solveX(int[] villages, int p) {
        int v = villages.length;
        if (p == 1) {
            return new int[]{villages[(v - 1) / 2]};
        } else {
            int pos = 0;
            int min = Integer.MAX_VALUE;
            for (int index = 0; index < v - 1; index++) {
                int p1 = index / 2;
                int p2 = (index + v) / 2;
                int tmp = 0;
                for (int k = 0; k < v; k++) {
                    if (k <= index) {
                        tmp += k <= p1 ? villages[p1] - villages[k] : villages[k] - villages[p1];
                    } else {
                        tmp += k <= p2 ? villages[p2] - villages[k] : villages[k] - villages[p2];
                    }
                }
                if (tmp < min) {
                    min = tmp;
                    pos = index;
                }
            }
            return new int[]{villages[pos / 2], villages[(pos + v) / 2]};
        }
    }
}
  • Postoffice.rar (1.4 KB)
  • 描述: 本文中用到的代码打包
  • 下载次数: 17
分享到:
评论
8 楼 Eastsun 2007-08-22  
哎,看来以后即便没有测试也不能说出来
也不是不想测试,没条件,这边网吧网速巨慢,实在没耐心去下个jdk。
7 楼 抛出异常的爱 2007-08-22  
rtdb 写道
这个帖为什么被投隐藏了??

> 并没有测试

贯出毛病来了。。。。
6 楼 Eastsun 2007-08-21  
rtdb 写道
这个帖为什么被投隐藏了??

> 并没有测试


晕,这种简单的DP算法,即便没有测试,我也有9成的把握可以一次写对。
而且这个主要讨论算法,DP算法已经给出状态描述与转移方程,这个才是核心部分,代码只是补充完备起见。
5 楼 rtdb 2007-08-21  
这个帖为什么被投隐藏了??

> 并没有测试
4 楼 Eastsun 2007-08-20  
Readonly 写道
这个题目有点意思,和小时候做的求最短路程算术题有点类似,是不是有直接的数学解?
另外,实际上村庄分布都是2维的,扩展一下这个题目,输入是一组村庄的x|y坐标,就变得更有实际意义一些了。

对于p=1时确实有直接的结果,我代码中也用到了。
对于一般情况至少我没想到有直接的结论,而且应该也不会有线性时间复杂度的算法。

如果把题目扩展到二维情形,事实上变成一个图论问题了,而且这个时候还得给出两两村庄之间的关系(有直接连接的道路?路程?)

ps:这个帖为什么被投隐藏了??

3 楼 realreal2000 2007-08-20  
我的思路是这样的不知道对不对,假设v=p那么,所有村庄都有一个邮局所以距离是0,所以当p减少1的时候就应该减去村庄之间距离最近的两个村庄任意一个的邮局,类推,减少2的时候找出所有村庄中路途最短的2条,查看然后除去2个村庄,类推。。。时间复杂度,首先对村庄距离排序,n2,然后取出节点,即可
2 楼 Readonly 2007-08-20  
这个题目有点意思,和小时候做的求最短路程算术题有点类似,是不是有直接的数学解?
另外,实际上村庄分布都是2维的,扩展一下这个题目,输入是一组村庄的x|y坐标,就变得更有实际意义一些了。
1 楼 walkandsing 2007-08-20  
用遗传算法也行

相关推荐

    顺序结构程序设计.pptx

    **第八章 指针** 指针是C语言的一大特色,它允许直接操作内存地址。本章讨论了指针变量的定义和使用,以及指针的运算,包括间接访问、赋值和加减运算。指针与数组、函数的结合使用,如指向数组的指针(行指针)和...

    顺序结构程序设计(ppt-13页).ppt

    【第8章 指针】是C语言的一大特色,指针变量用于存储内存地址,可以直接访问和修改变量的值。指针的基本运算包括间接访问、赋值和算术运算。指向数组和结构体的指针使得我们能够灵活地操作数据结构。函数参数也可以...

    [AB PLC例程源码][MMS_044666]Translation N-A.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    kolesar_3cd_01_0716.pdf

    kolesar_3cd_01_0716

    latchman_01_0108.pdf

    latchman_01_0108

    matlab程序代码项目案例:matlab程序代码项目案例MPC在美国高速公路场景中移动的车辆上的实现.zip

    matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    pimpinella_3cd_01_0716.pdf

    pimpinella_3cd_01_0716

    petrilla_01_0308.pdf

    petrilla_01_0308

    [AB PLC例程源码][MMS_041452]Speed Controls in Plastic Extrusion.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    强化学习驱动下DeepSeek技术创新及其对AI发展的影响

    内容概要:本文档由张卓老师讲解,重点探讨DeepSeek的技术革新及强化学习对未来AI发展的重要性。文章回顾了AI的历史与发展阶段,详细解析Transformer架构在AI上半场所起到的作用,深入介绍了MoE混合专家以及MLA低秩注意机制等技术特点如何帮助DeepSeek在AI中场建立优势,并探讨了当前强化学习的挑战和边界。文档不仅提及AlphaGo和小游戏等成功案例来说明强化学习的强大力量,还提出了关于未来人工通用智能(AGI)的展望,特别是如何利用强化学习提升现有LLMs的能力和性能。 适用人群:本资料适宜对深度学习感兴趣的研究人员、开发者以及想要深入了解人工智能最新进展的专业人士。 使用场景及目标:通过了解最新的AI技术和前沿概念,在实际工作中能够运用更先进的工具和技术解决问题。同时为那些寻求职业转型或者学术深造的人提供了宝贵的参考。 其他说明:文中提到了许多具体的例子和技术细节,如DeepSeek的技术特色、RL的理论背景等等,有助于加深读者对于现代AI系统的理解和认识。

    有师傅小程序开源版v2.4.14+前端.zip

    有师傅小程序开源版v2.4.14 新增报价短信奉告 优化部分细节

    [AB PLC例程源码][MMS_047333]Motor Sequence Starter with timers to start.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    商城二级三级分销系统(小程序+后台含源码).zip

    商城二级三级分销系统(小程序+后台含源码).zip

    li_3ck_01b_0918.pdf

    li_3ck_01b_0918

    nicholl_3cd_01_0516.pdf

    nicholl_3cd_01_0516

    1995-2022年 网络媒体关注度、报刊媒体关注度与媒体监督相关数据.zip

    媒体关注度是一个衡量公众对某个事件、话题或个体关注程度的重要指标。它主要反映了新闻媒体、社交媒体、博客等对于某一事件、话题或个体的报道和讨论程度。 媒体监督的J-F系数(Janis-Fadner系数)是一种用于测量媒体关注度的指标,特别是用于评估媒体对企业、事件或话题的监督力度。J-F系数基于媒体报道的正面和负面内容来计算,从而为公众、研究者或企业提供一个量化工具,以了解媒体对其关注的方向和强度。 本数据含原始数据、参考文献、代码do文件、最终结果。参考文献中JF系数计算公式。 指标 代码、年份、标题出现该公司的新闻总数、内容出现该公司的新闻总数、正面新闻数全部、中性新闻数全部、负面新闻数全部、正面新闻数原创、中性新闻数原创、负面新闻数原创,媒体监督JF系数。

    [AB PLC例程源码][MMS_040315]Double INC and Double DEC of INT datatype.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    [AB PLC例程源码][MMS_047773]Convert Feet to Millimeters.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    [AB PLC例程源码][MMS_042349]How to read-write data to-from a PLC using OPC in Visual Basic 6.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    matlab程序代码项目案例:matlab程序代码项目案例论文代码 多篇RMPC 鲁棒模型预测控制Paper-code-implementation.zip

    matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

Global site tag (gtag.js) - Google Analytics