题目链接

题意

给出 n 个餐厅,m 个停车场,现在要将 n 个餐厅中的 m 个变成停车场,使得每个餐厅到最近的停车场的距离之和最短,输出哪个餐厅变成停车场和它服务哪些餐厅,还有最短距离之和。

思路

首先确定在 i 到 j 之间,一定是选择 i 和 j 的中位数那个餐厅作为停车场可以使得i到j的餐厅到停车场的距离最短。

接下来定义状态 dp[i][j] 为前 i 个餐厅中有 j 个改装为停车场的最短距离之和。

设想如果前 j - 1 个停车场服务着前 k-1 个餐厅,那么剩下的最后一个停车场(第 j 个)就要服务 [k, i] 的餐厅了。

所以得到递推式:dp[i][j] = min(dp[i][j], dp[k-1][j-1] + 第k个餐厅到第i个餐厅的花费)。

这个花费可以预处理出来,定义 cost[i][j] 为 [i, j] 中修建一个停车场,其他 [i, j] 中的餐厅到这个停车场的距离之和。

还有一个难点就是输出路径的时候,用三个数组表示 dp[i][j] 的时候,最后一个停车场的位置,服务的餐厅的起点,服务的餐厅的终点,然后用 dfs 回溯的时候输出。

#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
const int N = 211;
const int INF = 0x3f3f3f3f;
int n, m, x[N], dp[N][N], cost[N][N];
int st[N][N], ed[N][N], id[N][N]; void dfs(int i, int j) {
if (i < 1 || j < 1) return ;
dfs(st[i][j]-1, j-1);
printf("Depot %d at restaurant %d serves ", j, id[i][j]);
if (st[i][j] == ed[i][j]) printf("restaurant %d\n", st[i][j]);
else printf("restaurants %d to %d\n", st[i][j], ed[i][j]);
} int main() {
int t = 0;
while (scanf("%d%d", &n, &m) && n && m) {
for (int i = 1; i <= n; i++) scanf("%d", &x[i]);
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
cost[i][j] = 0;
for (int k = i; k <= j; k++)
cost[i][j] += abs(x[k] - x[(i+j)/2]);
}
}
memset(dp, INF, sizeof dp);
dp[0][0] = 0;
for (int i = 1; i <= n; i++) { // 枚举当前要放多少个包裹
for (int j = 1; j <= i && j <= m; j++) { // 枚举仓库,要求仓库的数量比包裹数量少
for (int k = j; k <= i; k++) {
// 枚举从第k个包裹到第i个包裹全都放到最后一个仓库,
// 而且满足前面的j-1个仓库都至少一个包裹
int now = dp[k-1][j-1] + cost[k][i];
if (dp[i][j] > now) {
dp[i][j] = now;
st[i][j] = k; ed[i][j] = i; // st,ed 分别记录最后一个仓库的起点和终点
id[i][j] = (k + i) / 2; // id 记录的是位置
}
}
}
}
printf("Chain %d\n", ++t);
dfs(n, m);
printf("Total distance sum = %d\n\n", dp[n][m]);
}
return 0;
} /*
6 3
1 3 7 9 10 16
5 3
1 3 7 9 10
1 1
5
*/

在面试的时候被问到如果那个花费是距离的平方的时候,什么时候最优。

自己当场在平均值和中位数两者间试,试了一下还是被提示了,然后让我推,也推得不好。

然后就引申出了这个问题。然后当场不会做,因此在这里补一下。

具体的题目是:有 n 个 packages,m 个仓库,要让这些 packages 到最近的仓库的距离的平方之和最短,问最小的距离和。

#include <bits/stdc++.h>
using namespace std;
const int N = 211;
const int INF = 0x3f3f3f3f;
int n, m, x[N];
double dp[N][N], cost[N][N]; int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &x[i]);
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
double sum = 0;
for (int k = i; k <= j; k++)
sum += x[k];
sum /= (j - i + 1);
cost[i][j] = 0;
for (int k = i; k <= j; k++)
cost[i][j] += (x[k] - sum) * (x[k] - sum);
}
}
for (int i = 0; i <= n; i++) for (int j = 0; j <= m; j++) dp[i][j] = 1e9;
dp[0][0] = 0;
for (int i = 1; i <= n; i++) { // 枚举当前要放多少个包裹
for (int j = 1; j <= i && j <= m; j++) { // 枚举仓库,要求仓库的数量比包裹数量少
for (int k = j; k <= i; k++) {
// 枚举从第k个包裹到第i个包裹全都放到最后一个仓库,
// 而且满足前面的j-1个仓库都至少一个包裹
dp[i][j] = min(dp[i][j], dp[k-1][j-1] + cost[k][i]);
}
}
}
printf("%.2f\n", dp[n][m]);
return 0;
} /*
6 3
1 3 7 9 10 16
5 3
1 3 7 9 10
1 1
5
*/

POJ 1485:Fast Food(dp)&& 面试题的更多相关文章

  1. POJ.3624 Charm Bracelet(DP 01背包)

    POJ.3624 Charm Bracelet(DP 01背包) 题意分析 裸01背包 代码总览 #include <iostream> #include <cstdio> # ...

  2. POJ 2995 Brackets 区间DP

    POJ 2995 Brackets 区间DP 题意 大意:给你一个字符串,询问这个字符串满足要求的有多少,()和[]都是一个匹配.需要注意的是这里的匹配规则. 解题思路 区间DP,开始自己没想到是区间 ...

  3. [Codeforces 865C]Gotta Go Fast(期望dp+二分答案)

    [Codeforces 865C]Gotta Go Fast(期望dp+二分答案) 题面 一个游戏一共有n个关卡,对于第i关,用a[i]时间通过的概率为p[i],用b[i]通过的时间为1-p[i],每 ...

  4. poj 1485 dp

    转自:http://www.cnblogs.com/kuangbin/archive/2011/11/12/2246407.html [题目大意] 一条公路上有n个旅馆,选出其中k个设置仓库,一个仓库 ...

  5. 快餐店之间插入仓库,路最短,DP,POJ(1485)

    题目链接:http://poj.org/problem?id=1485 暂时我还没想出思路求路径.哈哈哈,先写一下中间步骤吧. #include <stdio.h> #include &l ...

  6. poj 1463 Strategic game DP

    题目地址:http://poj.org/problem?id=1463 题目: Strategic game Time Limit: 2000MS   Memory Limit: 10000K Tot ...

  7. ACM/ICPC 之 一道不太简单的DP面试题(Geeksforgeeks)

    题面来源:geeksforgeeks/1993 题解:geeksforgeeks 题目简述:给一个m*n的矩阵,计算从(1,1)到(m,n)的所有不回退路径中,经过k次转向后的路径有多少条 输入T个样 ...

  8. poj 3254 状压dp入门题

    1.poj 3254  Corn Fields    状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相 ...

  9. POJ 1260 Pearls 简单dp

    1.POJ 1260 2.链接:http://poj.org/problem?id=1260 3.总结:不太懂dp,看了题解 http://www.cnblogs.com/lyy289065406/a ...

随机推荐

  1. RPC的发展历史(本质就是双方定义好协议,传递参数后远程调用)

    服务器通讯原理就是一台socket服务器A,另一台socket客户端B,现在如果要通讯的话直接以流方式写入或读出. 这样能实现通讯,但有个问题.如何知道更多信息?比如需要发送流大小,编码,Ip等. 这 ...

  2. Cocos2d-x 脚本语言Lua介绍

    Cocos2d-x 脚本语言Lua介绍 本篇博客记录Lua学习.学习来自eoe论坛,Lua语言开发Cocos2d-x游戏入门视频教程,猛戳下面地址: http://www.eoeandroid.com ...

  3. WPF实现选项卡效果(2)——动态添加AvalonDock选项卡

    原文:WPF实现选项卡效果(2)--动态添加AvalonDock选项卡 简介 在前面一篇文章里面,我们使用AvalonDock实现了类似于VS的选项卡(或者浏览器的选项卡)效果.但是我们是通过xaml ...

  4. C#数字图像处理时注意图像的未用区域

    原文:C#数字图像处理时注意图像的未用区域 图1. 被锁定图像像素数组基本布局         如图1所示,数组的宽度并不一定等于图像像素数组的宽度,还有一部分未用区域.这是为了提高效率,系统要确定每 ...

  5. 使用NEWSEQUENTIALID解决GUID聚集索引问题

    原文:使用NEWSEQUENTIALID解决GUID聚集索引问题 UNIQUEIDENTIFIER做主键(Primary Key)是一件很方便的事情,在数据合并等操作中有不可替代的优势 但是由于普通的 ...

  6. C#高性能大容量SOCKET并发(五):粘包、分包、解包

    原文:C#高性能大容量SOCKET并发(五):粘包.分包.解包 粘包 使用TCP长连接就会引入粘包的问题,粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一 ...

  7. 为什么360、百度、腾讯出的Mac端云盘客户端都只有同步盘?(用户量小,同步盘开发成本低,Linux下都没有客户端)

    如题,顾名思义,同步盘是用来同步的,不具备增量的功能,像这三家在Windows端出的客户端都是即有同步也有增量的. 陆续出来的,可能大家更多的是跟随策略,不得不提dropbox是这样的形式.mac电脑 ...

  8. 《KVM虚拟化技术实战和原理解析》读书笔记(十几篇)

    第一章和第二章 第一章 虚拟化和云计算 Saas(软件即服务):将已经部署好的软件作为一种服务来提供,比如:Google Docs, Google Apps Paas(平台即服务):将开发环境作为一种 ...

  9. 在Windows IoT上使用网络摄像头

    在树莓派上可以使用它官方标配的摄像头,但是这个摄像头似乎不能被Windows IoT识别和使用.但是,可以在树莓派的USB口上插入任意型号的摄像头,就可以实现树莓派的拍摄功能. 关于摄像头的寻找和拍摄 ...

  10. Android-小小设置永久解决程序因为未捕获异常而异常终止的问题

    (一) 前言各位亲爱的午饭童鞋,是不是经常因为自己的程序中出现未层捕获的异常导致程序异常终止而痛苦不已?嗯,是的.. 但是,大家不要怕,今天给大家分享一个东东可以解决大家这种困扰,吼吼! (二) Un ...