题目链接:P4544 [USACO10NOV]Buying Feed G

建议做这题前先做下这题P1886 滑动窗口 /【模板】单调队列

我们可以用dp[i][j]表示当前走到前i个点,已经买了j吨饲料时到达下一个点的最小花费,可以推出状态转移方程方程dp[i][j]=min(dp[i][j],dp[i-1][k]+d*j^2+c*(j-k)),0<=k<=j(d为当前点到下一点的距离),,实际是dp[i][j]就是在所有满足条件的k中查找最小的一个dp[i-1][k]+d*j^2+c*(j-k),整理下该式子,得到:(dp[i-1][k]-c*k)+(d*j^2+c*j),这时我们可以发现该式子后半部分对于每个j为定值,与k无关,此时我们只需要查找小于k的所有数中(dp[i-1][k]-c*k)值最小且j-k<=fi(即当前商店买的饲料不能超出上限)的作为转移点即可,我们可以把(dp[i-1][k]-c*k)作为值,用单调队列维护,枚举j时每次把不合法队头的踢出去,把不如当前点更优的队尾也踢出去,放入当前点对应的(dp[i-1][k]-c*k),这样就使得队列中按(dp[i-1][k]-c*k)升序,每次队头即为花费最小的转移情况

具体注释和细节见代码:

#include<iostream>
#include<stack>
#include<list>
#include<set>
#include<vector>
#include<algorithm>
#include<math.h>
#include<numeric>
#include<map>
#include<cstring>
#include<queue>
#include<iomanip>
#include<cmath>
#include<queue>
#include <bitset>
#include<unordered_map>#ifndef local#define endl '\n'
#endif */
#define mkp make_pair
using namespace std;
using std::bitset;
typedef long long ll;
typedef long double ld;
const int inf=0x3f3f3f3f;
const ll MAXN=2e6+10;
const ll INF=1e18;
const ll N=2e5+100;
const ll mod=1e9+7;
const ll hash_p1=1610612741;
const ll hash_p2=805306457;
const ll hash_p3=402653189;
//-----------------------------------------------------------------------------------------------------------------*/
// ll head[MAXN],net[MAXN],to[MAXN],edge[MAXN]/*流量*/,cost[MAXN]//费用;
/*
void add(ll u,ll v,ll c,ll s){to[++cnt]=v;net[cnt]=head[u];edge[cnt]=c;cost[cnt]=s;head[u]=cnt;to[++cnt]=u;net[cnt]=head[v];edge[cnt]=0;cost[cnt]=-s;head[v]=cnt;
}
struct elemt{int p,v;
};
-----------------------------------
求[1,MAXN]组合式和逆元
ll mi(ll a,ll b){ll res=1;chile(b){if(b%2){res=res*a%mod;}    a=a*a%mod;b/=2;}return res;
}
ll fac[MAXN+10],inv[MAXN+10]
ll C(int m,int n){//组合式C(m,n); if(!n){return 1;}return fac[m]*(inv[n]*inv[m-n]%mod)%mod;
}
fac[0]=1;inv[0]=1;
for(ll i=1;i<=MAXN;i++){fac[i]=(fac[i-1]*i)%mod;inv[i]=mi(fac[i],mod-2);
}
---------------------------------unordered_map<int,int>mp;
//优先队列默认小顶堆 , greater<int> --小顶堆  less<int> --大顶堆
priority_queue<elemt,vector<elemt>,comp>q;
struct comp{public:bool operator()(elemt v1,elemt v2){return v1.v<v2.v;}
};set<int>::iterator it=st.begin();
*/
//emplace_back()  等于push_back(),但效率更高,传输pair时emplace_back(i,j)==push_back({i,j})
// vector<vector<int>>edge; 二维虚拟储存坐标
//-----------------------------------------------------------------------------------------------------------------*///map<int,bool>mp[N]; //emplace_back()
struct elemt{ll x,f,c;bool operator<(const elemt v){return x<v.x;//按坐标升序}
};//把商店定义为结构体,方便排序
//(x+d)^2=x^2+2xd+d^2;
ll dp[510][10010];//当前在第i个商店,已经有j吨饲料的花费
elemt a[510];
int main(){
/*cout<<setiosflags(ios::fixed)<<setprecision(8)<<ans<<endl;//输出ans(float)格式控制为8位小数(不含整数部分)*/
/*cout<<setprecision(8)<<ans<<endl;//输出ans(float)格式控制为8位小数(含整数部分)*/ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);//同步流
ll k,e,n;
cin>>k>>e>>n;
for(int i=1;i<=n;i++){cin>>a[i].x>>a[i].f>>a[i].c;
}
sort(a+1,a+n+1);//按坐标升序排序
a[n+1].x=e;
memset(dp,inf,sizeof(dp));
deque<pair<ll,ll>>q;//开两维分别维护dp[i-1][j]-a[i].c*j和k,队列内按dp[i-1][j]-a[i].c*j升序
for(int j=0;j<=a[1].f;j++){//初始化dp[1][j]=a[1].c*j+(a[2].x-a[1].x)*j*j;
}
for(int i=2;i<=n;i++){while(q.size()){q.pop_back();//把之前的清空}for(int j=0;j<=k;j++){while(q.size()&&q.back().first>=dp[i-1][j]-a[i].c*j){q.pop_back();//装的货物没有当前多,费用系数还比当前高(不如当前优)的可以踢出去了}q.push_back({dp[i-1][j]-a[i].c*j,j});//当前点放入队列while(q.size()&&q.front().second+a[i].f<j){//该商店全买完也不够j的踢出去q.pop_front();}dp[i][j]=min(dp[i][j],q.front().first+(a[i+1].x-a[i].x)*j*j+a[i].c*j);//最前面的就是最优的,//cout<<"i="<<i<<" j="<<j<<" dp="<<dp[i][j]<<" fr="<<q.front().first<<endl;}
}
//ll ans=dp[n][k]+(e-a[n].x)*k*k;//回到家的花费
cout<<dp[n][k]<<endl;return 0;
}

洛谷 P4544 [USACO10NOV]Buying Feed G)(单调队列优化DP)相关推荐

  1. 洛谷 - P1725 琪露诺(动态规划+单调队列优化)

    题目链接:点击查看 题目大意:给出一个由n个节点组成的数轴,每个点上都有一个权值,现在规定当在点x处时,下一步只能去[x+l,x+r]之间的任意一点,现在规定终点是点n之后的所有节点,现在问如何规划路 ...

  2. 洛谷P3195 [HNOI2008]玩具装箱TOY(单调队列优化DP)

    题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具, ...

  3. P2300 合并神犇(单调队列优化dp)

    P2300 合并神犇(单调队列优化dp) 令fif_ifi​​表示前iii​个数的最少合并次数,gig_igi​​表示在fif_ifi​​条件下的最小结尾值. 有转移方程:fi=min(fj+i−j− ...

  4. 算法笔记--单调队列优化dp

    单调队列:队列中元素单调递增或递减,可以用双端队列实现(deque),队列的前面和后面都可以入队出队. 单调队列优化dp: 问题引入: dp[i] = min( a[j] ) ,i-m < j ...

  5. poj 2373(单调队列优化dp)

    在长为L(<=1000000)的草地(可看成线段)上装喷水头,喷射是以这个喷水头为中心,喷水头的喷洒半径是可调节的调节范围为[a,b].要求草地的每个点被且只被一个喷水头覆盖,并且有些连续区间必 ...

  6. poj 1821(单调队列优化dp)

    题意:有一道线性篱笆由N个连续的木板组成.有K个工人,你要叫他们给木板涂色.每个工人有3个参数:L 表示 这个工人可以涂的最大木板数目,S表示这个工人站在哪一块木板,P表示这个工人每涂一个木板可以得到 ...

  7. 【计蒜客 - 蓝桥训练】蒜厂年会(单调队列优化dp,循环数列的最大子段和)

    题干: 在蒜厂年会上有一个抽奖,在一个环形的桌子上,有 nn 个纸团,每个纸团上写一个数字,表示你可以获得多少蒜币.但是这个游戏比较坑,里面竟然有负数,表示你要支付多少蒜币.因为这些数字都是可见的,所 ...

  8. 单调队列以及单调队列优化DP

    单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...

  9. POJ 1821 Fence(单调队列优化DP)

    题解 以前做过很多单调队列优化DP的题. 这个题有一点不同是对于有的状态可以转移,有的状态不能转移. 然后一堆边界和注意点.导致写起来就很难受. 然后状态也比较难定义. dp[i][j]代表前i个人涂 ...

最新文章

  1. 剑指offer:二位数组中的查找
  2. 俄研发新无线传电系统 隔20cm保持80%传输效率
  3. import,export的支持[nodejs]
  4. 骚年快答 | 微服务架构中的BFF到底是啥?
  5. C#码农的大数据之路 - 使用C#编写MR作业
  6. (十一)python3 只需3小时带你轻松入门——面向对象
  7. matlab中欠定方程组超定方程组_《数值天气预报》:球坐标系中的基本方程组
  8. python网页调用摄像头_Python调用摄像头
  9. C语言中的多字节字符与宽字符
  10. 一个做运营的朋友过来抱怨,现在HR谈薪都这么强硬吗?
  11. 用.htaccess禁止某IP访问
  12. 前端中LED字体的实现
  13. 安卓蓝牙USB连接热敏打印机二
  14. Unity Editor资源重命名
  15. SAP中看板拉料驱动MM物料移动的简单测试过程
  16. 硬件测试工程师养成日记第一篇
  17. 3d效果图制作傻瓜软件_3D效果图制作哪个软件是最适合的?
  18. 塞尔维亚国家队大名单:马蒂奇领衔,古德利落选
  19. 安装miniconda出现丢失api-mis-win-core-path-l1-1-0.dll的解决方案
  20. [第一讲]DSP28335将Flash中的代码拷贝到RAM中运行

热门文章

  1. NIVC-IPR[IPADDR]
  2. C++编程技巧:内码的转换技术
  3. 浅谈python(我心目中的python)
  4. css之-单行文本溢出显示省略号,多行文本溢出显示省略号
  5. 【HTML 教程系列第 19 篇】HTML 表格中的行合并与列合并
  6. Android开发之下载Tomcat服务器的文件到模拟器的SD卡
  7. hald进程 linux,centos hald 进程详解
  8. Express 极速掌握 1
  9. Git和Github的使用
  10. 用1、3、5、7 这4 个数字,能组成的互不相同且无重复数字的三位数有哪些?共有多少个?这些数的和为多少?