【动态规划】bzoj1705: [Usaco2007 Nov]Telephone Wire 架设电话线
可能是一类dp的通用优化
Description
最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线。 新的电话线架设在已有的N(2 <= N <= 100,000)根电话线杆上, 第i根电话线杆的高度为height_i米(1 <= height_i <= 100)。 电话线总是从一根电话线杆的顶端被引到相邻的那根的顶端 如果这两根电话线杆的高度不同,那么FJ就必须为此支付 C*电话线杆高度差(1 <= C <= 100)的费用。当然,你不能移动电话线杆, 只能按原有的顺序在相邻杆间架设电话线。Farmer John认为 加高某些电话线杆能减少架设电话线的总花费,尽管这项工作也需要支出一定的费用。 更准确地,如果他把一根电话线杆加高X米的话,他得为此付出X^2的费用。 请你帮Farmer John计算一下,如果合理地进行这两种工作,他最少要在这个电话线改造工程上花多少钱。
Input
* 第1行: 2个用空格隔开的整数:N和C
* 第2..N+1行: 第i+1行仅有一个整数:height_i
Output
* 第1行: 输出Farmer John完成电话线改造工程所需要的最小花费
Sample Input
2
3
5
1
4
输入说明:
一共有5根电话线杆,在杆间拉电话线的费用是每米高度差$2。
在改造之前,电话线杆的高度依次为2,3,5,1,4米。
Sample Output
输出说明:
最好的改造方法是:Farmer John把第一根电话线杆加高1米,把第四根加高2米,
使得它们的高度依次为3,3,5,3,4米。这样花在加高电线杆上的钱是$5。
此时,拉电话线的费用为$2*(0+2+2+1) = $10,总花费为$15。
题目分析
最基础的转移方程
因为这里每一个元素的转移只和前一个有关系,那么自然想到$f[i][j]$表示处理到第$i$个元素,同时它的高度为$j$的最小代价。
那么总状态数是$10^5\times 10^2$,每一次转移$10^4$。正常代码不刻意卡常是无法通过的。
从数形结合看转移
写下转移方程$f[i][j]=f[i-1][k]+(j-h[i])^2+c|j-k|$发现对于同一$f[i][j]$,其每次转移是一个开口向上的二次函数,这意味着枚举前一个高度$k$时若发现代价随高度递增,那么之后状态的也不可能会更优了。
#include<bits/stdc++.h>
#define R register int
const int maxn = ; int n,c,h[maxn],mx,ans;
int f[][],nw; inline int abs(int x){return x>?x:-x;}
int main()
{
memset(f, 0x3f3f3f3f, sizeof f);
scanf("%d%d",&n,&c);
ans = 0x3f3f3f3f;
for (R i=; i<=n; i++) scanf("%d",&h[i]), mx = h[i]<mx?mx:h[i];
for (R i=h[]; i<=mx; i++) f[][i] = (i-h[])*(i-h[]);
for (R i=; i<=n; i++)
{
for (R j=h[i]; j<=mx; j++)
{
R pre = 0x3f3f3f3f, w = (j-h[i])*(j-h[i]), val = ;
for (R k=h[i-]; k<=mx; k++)
{
val = f[nw^][k]+w+c*abs(j-k);
if (val < f[nw][j]) f[nw][j] = val;
else if (val > pre) break;
pre = val;
}
}
nw ^= ;
memset(f[nw], 0x3f3f3f3f, sizeof f[nw]);
}
for (R i=h[n]; i<=mx; i++)
ans = std::min(ans, f[nw^][i]);
printf("%d\n",ans);
return ;
}
从决策单调看转移
因为$f[i][j]=(j-h[i])^2+\{f[i-1][k]+c|j-k|\}$,而大括号内的式子与$j$无关,说明可以在枚举$j$的过程中选择最优的$k$。
至于这个选择也并不难。把式子大力拆开就是
$\begin{equation}\left\{\begin{array}{lr}f[i][j]=(j-h[i])^2+min(f[i-1][k]-c*k+c*j)\ \ (k<j) &\\ f[i][j]=(j-h[i])^2+min(f[i-1][k]+c*k-c*j)\ \ (k>j)\end{array}\right.\end{equation}$
这样就可以分别从小到大和从大到小各枚举一遍,天然保证了$j,k$之间的大小顺序。
做法来源:题解 P2885 【[USACO07NOV]电话线Telephone Wire】
#include<bits/stdc++.h>
#define R register int
const int maxn = ;
const int INF = 0x3f3f3f3f; int n,c,mx,nw,ans,h[maxn];
int f[][]; inline int min(int a, int b){return a>b?b:a;}
int main()
{
memset(f, 0x3f3f3f3f, sizeof f);
scanf("%d%d",&n,&c), ans = INF;
for (R i=; i<=n; i++) scanf("%d",&h[i]), mx = mx>h[i]?mx:h[i];
for (R i=h[]; i<=mx; i++) f[][i] = (i-h[])*(i-h[]);
for (R i=; i<=n; i++)
{
R k = INF;
for (R j=h[i-]; j<=mx; j++)
{
k = min(k, f[nw^][j]-c*j);
if (j >= h[i]) f[nw][j] = k+c*j+(j-h[i])*(j-h[i]);
}
k = INF;
for (R j=mx; j>=h[i]; j--)
{
k = min(k, f[nw^][j]+c*j);
f[nw][j] = std::min(k-c*j+(h[i]-j)*(h[i]-j), f[nw][j]);
}
nw ^= ;
memset(f[nw], 0x3f3f3f3f, sizeof f[nw]);
}
for (R i=h[n]; i<=mx; i++)
ans = min(ans, f[nw^][i]);
printf("%d\n",ans);
return ;
}
END
【动态规划】bzoj1705: [Usaco2007 Nov]Telephone Wire 架设电话线的更多相关文章
- bzoj1705[Usaco2007 Nov]Telephone Wire 架设电话线(dp优化)
1705: [Usaco2007 Nov]Telephone Wire 架设电话线 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 441 Solved: ...
- [bzoj1705] [Usaco2007 Nov]Telephone Wire 架设电话线
正常DP.. f[i][j]表示前i个电线杆,把第i个电线杆高度改为j的最少总费用.设原来电线杆高度为h[] f[i][j]=min{ f[i-1][k]+C*|j-k|+(j-h[i])^2,(k& ...
- BZOJ_1705_[Usaco2007 Nov]Telephone Wire 架设电话线_DP
BZOJ_1705_[Usaco2007 Nov]Telephone Wire 架设电话线_DP Description 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是 ...
- 【bzoj1705】[Usaco2007 Nov]Telephone Wire 架设电话线 dp
题目描述 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线. 新的电话线架设在已有的N(2 <= N < ...
- bzoj 1705;poj 3612:[Usaco2007 Nov]Telephone Wire 架设电话线
Description 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线. 新的电话线架设在已有的N(2 <= ...
- DP+滚动数组 || [Usaco2007 Nov]Telephone Wire 架设电话线 || BZOJ 1705 || Luogu P2885
本来是懒得写题解的…想想还是要勤发题解和学习笔记…然后就滚过来写题解了. 题面:[USACO07NOV]电话线Telephone Wire 题解: F[ i ][ j ] 表示前 i 根电线杆,第 i ...
- bzoj 1705: [Usaco2007 Nov]Telephone Wire 架设电话线——dp
Description 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线. 新的电话线架设在已有的N(2 <= ...
- 【BZOJ】1705: [Usaco2007 Nov]Telephone Wire 架设电话线
[题意]给定一排n根杆高度hi,一个常数C,杆升高x的代价为x^2,相邻两杆之间架设电话线代价为高度差*C,求总代价最小. [算法]DP+辅助数组优化 [题解]令f[i][j]表示第i根杆高度为j的最 ...
- BZOJ 1705: [Usaco2007 Nov]Telephone Wire 架设电话线 DP + 优化 + 推导
Description 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线. 新的电话线架设在已有的N(2 <= ...
随机推荐
- JQuery扩展和事件
一.jQuery事件 常用事件 blur([[data],fn]) 失去焦点 focus([[data],fn]) 获取焦点( 搜索框例子) change([[data],fn]) 当select下拉 ...
- Ubuntu 下修改Tomcat和Jetty默认的JDK和初始内存
修改/etc/default/tomcat 或者 /etc/default/jetty 文件 中的 JAVA_HOME 和 JAVA_OPTS
- D. Blocks 数学题
Panda has received an assignment of painting a line of blocks. Since Panda is such an intelligent bo ...
- IIS服务器访问网站出现403错误的解决方法
最近用织梦做了一个网站,因为织梦会在一个文件夹中生成网站的静态页面,而我们单击某个栏目时,一般程序都是直接去寻找该文件夹中的index.html文件的,当服务器中默认的索引文件不包括index.htm ...
- 采用React+Ant Design组件化开发前端界面(一)
react-start 基础知识 1.使用脚手架创建项目并启动 1.1 安装脚手架: npm install -g create-react-app 1.2 使用脚手架创建项目: create ...
- easyUI filebox限定文件大小
转载自:https://www.2cto.com/kf/201701/574667.html 侵删 easyui1.5filebox控件中增加文件大小的验证规则 2017-01-07 09:22:0 ...
- angularjs实现导航菜单切换高亮
<ul> <li ng-repeat="(index, item) in headerList"> <a ui-sref="{{item.h ...
- GoDaddy网站程序根目录 网站文件上传到虚拟主机哪个目录
用的linux虚拟主机,网站根目录为public_html,(window主机的目录为httpdocs)我们需要把本地做好的网站上传到此目录下 cPanel控制面板 - 文件管理器 - public_ ...
- ae(ArcEngine) java swing开发入门系列(2):ae的类型转换和Proxy类说明
做过C#版ae的都知道,操作同一个“对象”,用他的不同功能要转换到相应的接口,但java版有时不能直接做类型转换 例如下图在C#是可以的 但在java不行,这样转会报错,看IFeatureClass的 ...
- CRC检错技术原理
一.题外话 说来惭愧,一开始是考虑写关于CRC检错技术更深层次数学原理的,然而在翻看<Basic Algebra>后,我果断放弃了这种不切实际的想法.个人觉得不是因为本人数学水平差或者能力 ...