[POJ3612]telephone wire
来源:互联网 发布:淘宝考试以下不是催情 编辑:程序博客网 时间:2024/06/05 07:47
dp
我们设f[i][j]表示当考虑了前i座塔 第i座塔高度为j的最小花费
初始全部∞
我们有f[i][j]=min(f[i][j],f[i-1][k]+(j-a[i])^2+abs(j-k)*c)
这样我们枚举i j k时间复杂度nc²
然后只好考虑优化了
f[i][j]=min(f[i-1][k]-k*c)+j*c+(j-a[i])^2(j>=k)
f[i][j]=min(f[i-1][k]+k*c)-j*c+(j-a[i])^2(j<k)
你发现了什么……?对 min里面的式子可以直接O(c)求
这样我们将一个O(c²)的式子拆成了两个O(c)求的式子
时间复杂度O(n*2c) 空间复杂度O(n*c)
这样已经可过掉本题了
#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cstring>#include<cmath>using namespace std;const int INF = 0x7f7f7f7f;int dp[100001][101];int high[101],low[101];int n,c;int now[100001];inline int init(){int now=0;char c;bool flag=false;while(1){c=getchar();if(c>='0'&&c<='9'){now=now*10+c-'0';flag=true;}else if(flag)return now;}}int main(){n=init();c=init();for(int i=1;i<=n;i++){now[i]=init();for(int j=1;j<=100;j++){dp[i][j]=INF;}}dp[1][now[1]]=0;for(int i=now[1];i<=100;i++){dp[1][i]=pow((i-now[1]),2);}for(int i=2;i<=n;i++){low[0]=INF;high[0]=INF;high[101]=INF;for(int j=1;j<=100;j++){low[j]=min(dp[i-1][j]-j*c,low[j-1]);}for(int j=100;j>=1;j--){high[j]=min(dp[i-1][j]+j*c,high[j+1]);}for(int j=now[i];j<=100;j++){int p=pow(j-now[i],2);dp[i][j]=min(low[j]+(j*c)+p,p+high[j]-(j*c));}}int ans=INF;for(int i=1;i<=100;i++){ans=min(ans,dp[n][i]);}printf("%d",ans);return 0;}但是其实我们还能做到更好
考虑优化空间复杂度
我们发现每次转移只和上次的状态有关系
那么滚动数组
#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cstring>#include<cmath>using namespace std;const int INF = 0x7f7f7f7f;int dp[101];int high[101],low[101];int n,c;int now[100001];inline int init(){int now=0;char c;bool flag=false;while(1){c=getchar();if(c>='0'&&c<='9'){now=now*10+c-'0';flag=true;}else if(flag)return now;}}int main(){n=init();c=init();for(int i=1;i<=n;i++){now[i]=init();}for(int i=1;i<=100;i++){dp[i]=INF;}dp[now[1]]=0;for(int i=now[1];i<=100;i++){dp[i]=pow((i-now[1]),2);}for(int i=2;i<=n;i++){low[0]=INF;high[0]=INF;high[101]=INF;for(int j=1;j<=100;j++){low[j]=min(dp[j]-j*c,low[j-1]);}for(int j=100;j>=1;j--){high[j]=min(dp[j]+j*c,high[j+1]);dp[j]=INF;}for(int j=now[i];j<=100;j++){int p=pow(j-now[i],2);dp[j]=min(low[j]+(j*c)+p,p+high[j]-(j*c));}}int ans=INF;for(int i=1;i<=100;i++){ans=min(ans,dp[i]);}printf("%d",ans);return 0;}
不过挖个小坑 也希望看到这篇博文的人能帮我一下
1、求high函数时 为什么要从上往下?
好吧我自己找到答案了
low[j]表示的貌似是高度为j时从下往上的最小的花费
high[j]表示的貌似是高度为j时从上往下的最小的花费
这样low[j],high[j]肯定是类似一个区间的东西 表示的是区间内最小值 这样每次转移一定没问题
感谢fyj404的答案
首先 我们要确定一个事实 每次上边j转移都是从1->j和j->c转移的
我们用low和high实际上维护的是1->j的最小值和j->c的最小值 也就是我们要转移的东西
2、使用滚动数组时为什么一定要置为∞?(我觉得不变也可以吧 因为每次转移的状态应该只和上次的部分状态有关系)
这个问题还不确定
0 0
- [POJ3612]telephone wire
- POJ3612——Telephone Wire
- 【POJ3612】【USACO 2007 Nov Gold】 1.Telephone Wire 动规
- poj 3612 Telephone Wire
- openjudge telephone wire
- poj 3612 Telephone Wire
- BZOJ1705 Telephone Wire 架设电话线
- P2885 [USACO07NOV]电话线Telephone Wire
- poj3612
- [BZOJ1705] [Usaco2007 Nov]Telephone Wire 架设电话线
- 1705: [Usaco2007 Nov]Telephone Wire 架设电话线
- 译文及题解 电话线Telephone Wire(动态规划)
- Telephone
- telephone conference
- telephone interview
- Android telephone
- Telephone interview
- Telephone Meeting
- 【Day21】关于mysql数据库索引所涉及的一些知识(新)
- Unity5.4.1与NGUI出现的问题Ignoring menu item NGUI because it is in no submenu!
- 设计模式之原型模式20
- Java线程锁(二)——循环打印ABC
- ovs vswitchd的启动分析
- [POJ3612]telephone wire
- 用“射同基反”原则判断电路是否起振
- 素数筛选法
- java jdk 1.8 新增特性->( lambda特性)
- IT搬砖者的内心独白
- 字符串的旋转
- JAVA 学习之集合
- 数组字符串类笔试题
- 用户级线程和内核级线程的区别