poj1180 dp斜率优化
2013-11-18 16:01
369 查看
解题报告
题目
:http://poj.org/problem?id=1180
题目大意
:给定n个工作,可以任意分组,最后每个工作的花费是O[i]*f[i],其中O[i]是i所在分组整体被完成的时间,给定开始时间,机器启动时间S,求完成所有任务最小花费。
算法
:动态规划 +
斜率优化
思路
:首先想到了dp[i] = min{dp[j]
+ (S + O[j] + sum[i] – sum[j]) * f[i] ) (j <
i)但是这是二维的方程,需要优化成一维,但是这个式子很难化解成f[i] – f[j] = k (g[i] – g[j]) +
b的形式,而且如果将j和i分在一组,O[j]的值也会改变,无法用斜率搞,最后看了网上大牛才知,设定状态
Dp[i]
= min{dp[j] + (S + sumt[i] – sumt[j] ) * sumf[i]
{sumt[i] =t[i] + t[i + 1]…….}, sumf[i] = f[i] + f[i +
1]….
然后化解这个式子就能斜率优化了。这里处理O[i]也算是一个技巧了,将由工作i导致的i之后的花费加到i上,这样每次的开始时间都成为了0,从后往前dp即可,其他都一样。
提交情况 Accepted 1
次
经验与收获
:
对斜率优化理解还是不到位。
AC
code:
#include <stdio.h>
#define MAXN 10010
intsumt[MAXN], sumf[MAXN], dp[MAXN], strack[MAXN], S,
T[MAXN], F[MAXN], n;
bool rise(int k,
int j, int i){
return (dp[k] - dp[j])
<= sumf[i] * (sumt[k] - sumt[j]);
}
boolturn_right(int p,
int q, int r){
int t1 = (dp[p] - dp[q]) * (sumt[q]
- sumt[r]);
int t2 = (dp[q] - dp[r]) * (sumt[p]
- sumt[q]);
return t1 >=
t2;
}
int main(){
int res, top, i;
sumt[0] = sumf[0] = 0;
while(~scanf("%d", &n)){
scanf("%d",
&S);
for(i = 1; i <= n; i
++)
scanf("%d %d",
&T[i], &F[i]);
sumt[n + 1] = sumf[n + 1] = 0;
for(i = n; i > 0; i
--){
sumt[i] = sumt[i + 1] + T[i];
sumf[i] = sumf[i + 1] + F[i];
}
strack[0] = dp[n + 1] = top = res = 0;
strack[++top] = n;
dp
= (S + sumt
) * sumf
;
for(i = n - 1; i >
0; i --){
for(; res < top
&& rise(strack[res + 1],
strack[res], i); res ++);
dp[i] = dp[strack[res]] + (S + sumt[i] - sumt[strack[res]]) *
sumf[i];
while(top > 0
&& turn_right(strack[top - 1],
strack[top], i)) --top;
strack[++top] = i;
if(res > top) res =
top;
}
printf("%d\n",
dp[1]);
}
return 0;
}
题目
:http://poj.org/problem?id=1180
题目大意
:给定n个工作,可以任意分组,最后每个工作的花费是O[i]*f[i],其中O[i]是i所在分组整体被完成的时间,给定开始时间,机器启动时间S,求完成所有任务最小花费。
算法
:动态规划 +
斜率优化
思路
:首先想到了dp[i] = min{dp[j]
+ (S + O[j] + sum[i] – sum[j]) * f[i] ) (j <
i)但是这是二维的方程,需要优化成一维,但是这个式子很难化解成f[i] – f[j] = k (g[i] – g[j]) +
b的形式,而且如果将j和i分在一组,O[j]的值也会改变,无法用斜率搞,最后看了网上大牛才知,设定状态
Dp[i]
= min{dp[j] + (S + sumt[i] – sumt[j] ) * sumf[i]
{sumt[i] =t[i] + t[i + 1]…….}, sumf[i] = f[i] + f[i +
1]….
然后化解这个式子就能斜率优化了。这里处理O[i]也算是一个技巧了,将由工作i导致的i之后的花费加到i上,这样每次的开始时间都成为了0,从后往前dp即可,其他都一样。
提交情况 Accepted 1
次
经验与收获
:
对斜率优化理解还是不到位。
AC
code:
#include <stdio.h>
#define MAXN 10010
intsumt[MAXN], sumf[MAXN], dp[MAXN], strack[MAXN], S,
T[MAXN], F[MAXN], n;
bool rise(int k,
int j, int i){
return (dp[k] - dp[j])
<= sumf[i] * (sumt[k] - sumt[j]);
}
boolturn_right(int p,
int q, int r){
int t1 = (dp[p] - dp[q]) * (sumt[q]
- sumt[r]);
int t2 = (dp[q] - dp[r]) * (sumt[p]
- sumt[q]);
return t1 >=
t2;
}
int main(){
int res, top, i;
sumt[0] = sumf[0] = 0;
while(~scanf("%d", &n)){
scanf("%d",
&S);
for(i = 1; i <= n; i
++)
scanf("%d %d",
&T[i], &F[i]);
sumt[n + 1] = sumf[n + 1] = 0;
for(i = n; i > 0; i
--){
sumt[i] = sumt[i + 1] + T[i];
sumf[i] = sumf[i + 1] + F[i];
}
strack[0] = dp[n + 1] = top = res = 0;
strack[++top] = n;
dp
= (S + sumt
) * sumf
;
for(i = n - 1; i >
0; i --){
for(; res < top
&& rise(strack[res + 1],
strack[res], i); res ++);
dp[i] = dp[strack[res]] + (S + sumt[i] - sumt[strack[res]]) *
sumf[i];
while(top > 0
&& turn_right(strack[top - 1],
strack[top], i)) --top;
strack[++top] = i;
if(res > top) res =
top;
}
printf("%d\n",
dp[1]);
}
return 0;
}
相关文章推荐
- [POJ1180&POJ3709]Batch Scheduling&K-Anonymous Sequence 斜率优化DP
- 【JZOJ 3432】服务器 斜率优化DP常见问题&详细解答
- 单调队列 && 斜率优化dp 专题
- 斜率优化dp再探 (模板) BZOJ 3156 & BZOJ 4518
- 斜率优化DP(POJ1180 && POJ3709)
- hdu3507&nbsp;动态规划+斜率优化
- 斜率优化dp专题 & BZOJ1010 HNOI2008 玩具装箱toy
- Poj 2018 Best Cow Fences(分数规划+DP&&斜率优化)
- BZOJ 1492 斜率优化dp && cdq分治
- HYSBZ/BZOJ 1010 [HNOI2008] 玩具装箱 - dp&斜率优化
- [BZOJ 3156] 防御准备 · 斜率优化DP
- [BZOJ 1010] HNOI 2008 玩具装箱toy · 斜率优化DP
- [BZOJ 1597] Usaco2008 Mar 土地购买 · 斜率优化DP
- BZOJ 3437 小P的牧场(斜率优化DP)
- bzoj 1010 [HNOI2008]玩具装箱toy(DP的斜率优化)
- [BZOJ3963][WF2011][CDQ分治][斜率优化][DP]MachineWorks
- hdu2829 Lawrence 斜率优化DP
- ListView&nbsp;中Adapter的优化
- BZOJ 1010 玩具装箱 toy (DP斜率优化)
- bzoj 1096: [ZJOI2007]仓库建设 斜率优化+:DP