Sell Feed - Monotone queue optimization dp

Title Description

John drove to town, he would go home with a K tons of feed. Transporting feed costs money, if his car had X tons of feed per kilometer will have to spend X ^ 2 million, it is necessary to drive kilometers D D * X ^ 2 million. John N can be purchased from feed stores, the stores are all in a coordinate axis, the position of the i-th store is Xi, the price of feed for the Ci yuan per ton, inventory Fi.  
John = O began to move forward in a positive direction from the axis coordinates X, his home on the coordinates X = E. In order to bring home tons of feed K, John minimum cost is how much? 
Assuming that all of the store's inventory and no less than K.  
For example, assume that three shops, shown as follows:  
coordinates X = 1 X = 3 X =   4 E = 5
Stock 111  
price 122  
, if K = 2, the best choice is to home John money close two stores to buy feed, then spent on the road is 1 + 4 = 5, the money is spent in the store 2 + 2 = 4, a total of nine yuan. 

Thinking

$ dp [i] [j] $ denotes the minimum cost to $ $ I $ J $ with a ton of feed. (Note that this time i have not bought the store )

In each store, we can choose to buy or not to buy, enumerate $ $ k $ with the feed before i-1 $, then the $ dp [i]] [j] = min (dp [i-1] [k] + j * j * (d [i] -d [i-1]) + (jk) * c [i]) $

整理一下:$dp[i][j]=min(dp[i-1][k]-k*c[i]+j*j*(d[i]-d[i-1])+j*c[i])$

Monotone queue maintains that the dp [i-1] [k] to transfer the smallest k.

code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int K=10010;
const int N=510;
LL f[N][K];
int k,hm,n;
struct FARM
{
    LL x,v,w;
}a[N];
LL d[N];
 
bool cmp(FARM a,FARM b)
{
    return a.x<b.x;
}
 
int main()
{
    scanf("%d%d%d",&k,&hm,&n);
    for(int i=1;i<=n;i++)scanf("%lld%lld%lld",&a[i].x,&a[i].v,&a[i].w);
    sort(a+1,a+1+n,cmp);
    n++;a[n]=(FARM){hm,0,0};
    for(int i=1;i<=n;i++)
    d[i]=a[i].x-a[i-1].x;
    memset(f,0x3f,sizeof(f));
    f[0][0]=0;
    for(int i=1;i<=n;i++)
    {
        deque<int>q;
        for(int j=0;j<=k;j++)
        {
            while(!q.empty()&&j-q.front()>a[i-1].v)q.pop_front();
            while(!q.empty()&&f[i-1][q.back()]-a[i-1].w*q.back()>=f[i-1][j]-a[i-1].w*j)
            q.pop_back();
            q.push_back(j);
            int p=q.front();
            if(!q.empty())f[i][j]=f[i-1][p]-a[i-1].w*p+a[i-1].w*j+j*j*d[i];
             
        }
    }
    cout<<f[n][k];
}

 

Guess you like

Origin www.cnblogs.com/THRANDUil/p/11563898.html