jzoj5259 线性规划问题 (巧妙设状态的dp)
2017-08-11 16:20
267 查看
题意
n<=1e3,p<=1e4
保证ai<=bi
分析
暴力做法很简单,设fi,j,k表示suma=j,sumb=k的最小的c就可以了,转移显然.观察题目给的约束,j,k分别在P的两边。
我们简化状态,设fi,x表示i,j分别在j两边的最小c值。
如何转移?
考虑x的意义j<=x<=k
因为是取min,所以重复是没有问题的。 只需要考虑不漏下。
感性理解:
想象一个数轴上有j<=x<=k,j往前a[i],k往前b[i],一定在这些j′,k′中间的x′能怎么取?因为a[i]<=b[i],所以j−a[i]<=k−b[i],也就是k−j>=b[i]−a[i]。
满足k−j=b[i]−a[i]的(j,k)对会只剩一个x’能够包含,所以这些x’必须要转移。不难得出这些x’就是[x−bi,x−ai]
那么不卡在这个限制上的(j2,k2)对能被x′∈[x−bi,x−ai]包含吗?是会被包含的。 比较显然,而且证明起来很难表述。
手玩几个试试就知道了,因为它x’的区间与[x−bi,x−ai]是一定有交集的。
这样直接用单调队列维护就可以了。
O(np)
Demo
#include <cstdio> #include <iostream> #include <cstring> const int N=1010,P=1e4+10; using namespace std; int n,p; int a ,b ,c ,ans; int f [P]; int Q[P],head,tail; int main() { freopen("3.in","r",stdin); int T; for (cin>>T; T; T--) { cin>>n>>p; for (int i=1; i<=n; i++) scanf("%d",&a[i]); for (int i=1; i<=n; i++) scanf("%d",&b[i]); for (int i=1; i<=n; i++) scanf("%d",&c[i]); memset(f,127,sizeof f); f[0][0]=0; for (int i=1; i<=n; i++) { head=1; int rd=0; tail=0; for (int j=0; j<=p; j++) { for (; rd<=j-a[i]; ++rd) { while (head<=tail && f[i-1][ Q[tail] ]>=f[i-1][rd]) --tail; Q[++tail]=rd; } while (head<=tail && Q[head]<j-b[i]) ++head; f[i][j]=f[i-1][j]; if (head<=tail) f[i][j]=min(f[i][j],f[i-1][Q[head]]+c[i]); } } if (f [p]==f[n+1][0]) printf("IMPOSSIBLE!!!\n"); else printf("%d\n",f [p]); } }
相关文章推荐
- JZOJ5259. 线性规划问题
- 动态规划解TSP问题(状态压缩dp)
- 网络流与线性规划24题10餐巾计划问题
- 线性规划与网络流24——最小路径覆盖问题
- 状态压缩DP与TSP问题
- 旅行商问题 (状态压缩DP)
- 【网络流与线性规划24题】【机器人路径规划问题】【IDA*】【题解】
- 线性规划与网络流24——分配问题
- 3进制状态压缩DP——HDU3001 Travelling 旅行商问题
- 【线性规划与网络流24题 5】圆桌问题
- POJ 状态DP+ 01 背包问题
- 线性规划问题和MATLAB函数linprog的使用
- 线性规划与网络流24题 餐巾计划问题
- 深入浅出数据分析:最优化-用Excel求解一个线性规划问题
- mmc线性0-1规划问题
- 线性规划问题之MATLAB实现
- 线性动态规划——解最长公共子序列问题
- 动态规划之状态压缩dp入门
- 状态压缩动态规划 -- 棋盘问题 POJ 1321
- hdu 5119 (类似于划分数的状态定义) (DP中的计数问题)