您的位置:首页 > 其它

UVALive - 5097(斜率DP)

2017-10-27 22:48 281 查看
题解:先把宽按从大到小排序如果宽相同就按高度从大到小排序,接着把宽度和高度都小于某个点的删除掉,然后就可以求出方程就是dp[i][j] = min{dp[i-1][a]+x[a+1]*y[j]};

然后斜率优化的的话用队列维护可以化为dp[j]+x[j+1]*y[i]<dp[k]+x[k+1]*y[i],k<j当满足这个条件时候就可以把队头删除掉,加入队列的话满足(dp[b]-dp[c])*(x[c+1]-x[i+1])>=(dp[i]-dp[c])*(x[c+1]-x[b+1]),i>b>c就可以把队尾的的b删除掉

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
typedef long long int ll;
using namespace std;
#define ls rt*2
#define rs rt*2+1
#define mid (L+R)/2
#define lson ls,L,mid
#define rson rs,mid+1,R
#define x first
#define y second
typedef pair<int,int> pii;
const int mx = 5e4+5;
deque<int>q;
ll dp[105][mx];
int n,k;
struct node{
int x,y;
bool operator<(const node a)const{
if(x!=a.x) return x>a.x;
return y>a.y;
}
}a[mx];
int cnt;
void erase_front(int i,int j){
while(q.size()>=2){
int b = q.front();
q.pop_front();
int c = q.front();
if(dp[i][c]-dp[i][b]>1ll*(a[b+1].x-a[c+1].x)*a[j].y){
q.push_front(b);
return;
}
}
}
void insert(int i,int j){
while(q.size()>=2){
int b = q.back();
q.pop_back();
int c = q.back();
if((dp[i][b]-dp[i][c])*(a[c+1].x-a[j+1].x)<(dp[i][j]-dp[i][c])*(a[c+1].x-a[b+1].x)){
q.push_back(b);
break;
}
}
q.push_back(j);
}
void solve(){
dp[0][0] = 0;
k = min(k,cnt);
n = min(cnt,n);
ll ans = 1e15;
for(int i = 1; i <= k; i++){
q.push_back(i-1);
for(int j = i; j <= n; j <= j++)
if(i==1)
dp[i][j] = 1ll*a[1].x*a[j].y;
else{
erase_front(i-1,j);
int c = q.front();
dp[i][j] = dp[i-1][c]+1ll*a[c+1].x*a[j].y;
insert(i-1,j);

}
while(!q.empty())
q.pop_back();
ans = min(ans,dp[i]
);
}
printf("%lld\n",ans);
}
int main(){
while(scanf("%d%d",&n,&k)!=EOF){
for(int i = 1; i <= n; i++)
scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+1+n);
cnt = 1;
for(int i = 1; i <= n; i++)
if(a[cnt].y < a[i].y)
a[++cnt] = a[i];
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: