斜率優化(凸包優化)DP問題acm
#寫在前面
這類問題做的過程比較偏數學
對於狀態轉移方程需要經過一些數學上的整理
之後幾道題步步深入斜率優化問題
##任務安排1
https://www.acwing.com/problem/content/302/
----c++版
#include<iostream>
#include<algorithm>
using namespace std;
#include<cstring>
const int N=5010;
int n,s;
int sumt[N],sumc[N];
int f[N];
int q[N];
int main(){
scanf("%d%d", &n, &s);
for(int i=1; i<=n; i++){
int t, c;
scanf("%d%d", &t, &c);
sumt[i] = sumt[i-1]+t;
sumc[i] = sumc[i-1]+c;
}
memset(f, 0x3f, sizeof f);
f[0] = 0;
for(int i=1; i<=n; i++)
for(int j=0; j<i; j++)
f[i] = min(f[i], f[j]+sumt[i]*(sumc[i]-sumc[j])+s*(sumc[n]-sumc[j]));
printf("%d\n", f[n]);
return 0;
}
##任務安排2
https://www.acwing.com/problem/content/303/
這題僅僅是資料範圍擴大了
----c++版
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=300010;
int n,s;
ll c[N], t[N];
ll f[N];
int q[N];
int main(){
scanf("%d%d", &n, &s);
for(int i=1; i<=n; i++){
scanf("%lld%lld", &t[i], &c[i]);
t[i]+=t[i-1];
c[i]+=c[i-1];
}
int hh=0, tt=0;
q[0]=0;//f[0]也是一個可選答案
for(int i=1; i<=n; i++){
//佇列中至少有兩個數
while(hh < tt && (f[q[hh+1]]-f[q[hh]]) <= (t[i]+s)*(c[q[hh+1]]-c[q[hh]])) hh++;
int j = q[hh]; //對頭,即第一個斜率大於當前斜率的點
f[i] = f[j]-(t[i]+s)*c[j]+t[i]*c[i]+s*c[n];
while(hh < tt && (f[q[tt]]-f[q[tt-1]])*(c[i]-c[q[tt]]) >= (f[i]-f[q[tt]])*(c[q[tt]]-c[q[tt-1]]))
tt--;//去掉隊尾的
q[++tt] = i;
}
printf("%lld", f[n]);
return 0;
}
##任務安排3
https://www.acwing.com/problem/content/304/
與上一題唯一的區別就是 t 可能是負數了
----c++版
#include<iostream>
#include<algorithm>
using namespace std;
const int N=300010;
typedef long long ll;
int n,s;
ll t[N],c[N];
ll f[N];
int q[N];
int main(){
scanf("%d%d", &n, &s);
for(int i=1; i<=n; i++){
scanf("%lld%lld", &t[i], &c[i]);
t[i]+=t[i-1];
c[i]+=c[i-1];
}
int hh=0, tt=0;
q[0]=0;
for(int i=1;i<=n;i++){
int l=hh, r=tt;
while(l<r){
int mid=l+r>>1;
if(f[q[mid+1]]-f[q[mid]]>(t[i]+s)*(c[q[mid+1]]-c[q[mid]]))r = mid;
else l=mid+1;
}
int j = q[r];
f[i] = f[j]-(t[i]+s)*c[j]+t[i]*c[i]+s*c[n];
while(hh < tt && (double)(f[q[tt]]-f[q[tt-1]])*(c[i]-c[q[tt-1]]) >= (double)(f[i]-f[q[tt-1]])*(c[q[tt]]-c[q[tt-1]]))
tt--;//去掉隊尾的
q[++tt] = i;
}
printf("%lld", f[n]);
return 0;
}
##運輸小貓
https://www.acwing.com/problem/content/305/
----c++版
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100010, M=100010, P=110;
int n,m,p;
ll d[N], t[N], a[N], s[N];
ll f[P][M];
int q[M];
ll get_y(int k, int j){
return f[j-1][k]+s[k];
}
int main(){
scanf("%d%d%d", &n,&m,&p);
for(int i=2; i<=n; i++){
scanf("%lld", &d[i]);
d[i]+=d[i-1];
}
for(int i=1; i<=m; i++){
int h;
scanf("%d%lld", &h, &t[i]);
a[i] = t[i]-d[h];//直接過濾掉了其他的山,只剩下留小貓的
}
sort(a+1, a+m+1);
for(int i=1; i<=m; i++)s[i]=s[i-1]+a[i];
memset(f, 0x3f, sizeof f);
for(int j=0; j<=p; j++) f[j][0] = 0;//j個飼養員處理0只小貓都是0
for(int j=1; j<=p; j++){
int hh=0, tt=0;
q[0] = 0;
for(int i=1;i<=m;i++){
while(hh<tt && (get_y(q[hh+1],j)-get_y(q[hh],j))<=a[i]*(q[hh+1]-q[hh]))hh++;
int k = q[hh];
f[j][i] = f[j-1][k]-a[i]*k+s[k]+a[i]*i-s[i];
while(hh<tt && (get_y(q[tt],j)-get_y(q[tt-1],j))*(i-q[tt])>=
(get_y(i,j)-get_y(q[tt],j))*(q[tt]-q[tt-1]))tt--;
q[++tt]=i;
}
}
printf("%lld", f[p][m]);
return 0;
}
相關文章
- 【DP】斜率優化初步優化
- 斜率優化DP總結優化
- 凸優化問題優化
- 03-凸優化問題優化
- 凸優化優化
- 洛谷P2365/5785 任務安排 題解 斜率優化DP優化
- 斜率最佳化 DP
- 斜率最佳化dp
- 斜率優化學習筆記優化筆記
- 斜率優化動態規劃優化動態規劃
- BZOJ 1492 [NOI2007]貨幣兌換Cash:斜率優化dp + cdq分治優化
- 淺談斜率最佳化DP
- 凸最佳化問題
- 數值最優化—優化問題的解(二)優化
- 多重揹包問題的單調佇列優化佇列優化
- 為什麼凸優化這麼重要?優化
- 無約束凸優化演算法優化演算法
- 洛谷P4027 [NOI2007]貨幣兌換(dp 斜率優化 cdq 二分)優化
- WQS 二分 & 凸最佳化dp
- go的編譯優化問題Go編譯優化
- 【離散優化】覆蓋問題優化
- 記一個效能優化問題優化
- N皇后問題(各種優化)優化
- 01揹包優先佇列優化佇列優化
- AI工程師必備技能 - 凸優化介紹AI工程師優化
- 【課程筆記】中科大凸優化(二)筆記優化
- 【課程筆記】中科大凸優化(三)筆記優化
- 四邊形不等式優化DP優化
- [20181119]使用sql profile優化問題.txtSQL優化
- webpack dll打包重複問題優化Web優化
- iOS問題整理08----效能優化iOS優化
- [20211210]優化遇到的奇怪問題.txt優化
- GitHub 訪問優化Github優化
- Android效能優化——效能優化的難題總結Android優化
- sql優化專題SQL優化
- 前端效能優化(JS/CSS優化,SEO優化)前端優化JSCSS
- RecyclerView使用,優化,條目閃爍問題View優化
- 關於vue的webpack打包優化問題VueWeb優化