Vijos 1243 生产产品 (优先队列优化的动态规划)

题意:中文题。不说了。

注意一些地方,机器的执行过程是没有顺序的,而且每个机器可以用多次。第一次执行的机器不消耗转移时间K。

用dp[i][j]表示第i个机器完成第j个步骤的最短时间,sum[j][i]表示第i个机器完成前j个步骤的时间。

比较容易想到一个朴素的状态转移方程:

dp[i][j]=min{dp[k][j‘]+sum[j][i]-sum[j‘][i]}+K 
(j-j‘<l),(i!=k)

这里状态是O(n*m),转移是O(n*l),一定会超时,需要优化。

方程变形得dp[i][j]=min{dp[k][j‘]-sum[j‘][i]}+sum[j][i]+K

在这里如果把k和i看作常数,那么dp[k][j‘]-sum[j‘][i]是一个只和j‘量。由于k和i比较小,我们完全可以枚举k和i的所有情况,我们定义该量为opt[i][k],我们只需要维护j-l到j这段范围内这个量的最小值即可。这里使用二维的优先队列来解决。转移部分优化成O(n)。总时间可以接受。

笔者曾经一度被初始化部分卡住,所以这里着重解释一下初始化部分的写法。

当j=1时,j唯一可能转移而来的状态就是j=0,所以首先我们要在队列里存入所有队列里存入j=0的下标,但这样还不够,还要更新j=0的状态,j=0时opt[i][k]这个变量是等于0,所以对应opt[i][k]=dp[k][0]+sum[0][i],需要把dp[k][0]和sum[0][i]都初始化为0。其他情况下,dp[i][j]都初始化为INF。

可以这么写:


    memset(dp,0x7f,sizeof(dp));
for(int i=1; i<=n; ++i)
dp[i][0]=0;
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
dq[i][j].push_back(0);

或者是下标j从0开始枚举,这样就包含了将j=0存入队列的部分,而初始化j=0的状态还是要自己来写。

维护队首和队尾的部分,要一次性全部完成,不能一次维护一个。

最后要注意的一个地方就是第一个机器是不花费转移机器的时间的,所以时间里要减去一个K。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<string>
#include<vector>
#include<deque>
using namespace std;
int time[100005][6];
int dp[6][100005];
deque<int> dq[6][6];
int calc(int i,int j,int k)
{
return dp[k][j]-time[j][i];
}
int main()
{
int m,n,K,l;
scanf("%d%d%d%d",&m,&n,&K,&l);
for(int i=1; i<=n; ++i)
{
for(int j=1; j<=m; ++j)
{
int t;
scanf("%d",&t);
time[j][i]=time[j-1][i]+t;
}
}
int ans=0x7fffffff;
memset(dp,0x7f,sizeof(dp));
for(int i=1; i<=n; ++i)
dp[i][0]=0;
for(int j=0; j<=m; ++j)
{
for(int i=1; i<=n; ++i)
for(int k=1; k<=n; ++k)
if(i!=k) while(!dq[i][k].empty()&&(j-dq[i][k].front())>l) dq[i][k].pop_front();
for(int i=1; i<=n; ++i)
for(int k=1; k<=n; ++k)
if(i!=k)
{
int a=0,b=0;
if(!dq[i][k].empty()) a=calc(i,dq[i][k].front(),k);
b=time[j][i]+K;
dp[i][j]=min(dp[i][j],a+b);
}
for(int i=1; i<=n; ++i)
for(int k=1; k<=n; ++k)
if(i!=k)
{
while(!dq[i][k].empty()&&(calc(i,dq[i][k].back(),k)>=calc(i,j,k))) dq[i][k].pop_back();
dq[i][k].push_back(j);
}
}
for(int i=1; i<=n; ++i)
ans=min(ans,dp[i][m]);
printf("%d\n",ans-K);
return 0;
}

Vijos 1243 生产产品 (优先队列优化的动态规划),布布扣,bubuko.com

时间: 2024-08-23 15:16:15

Vijos 1243 生产产品 (优先队列优化的动态规划)的相关文章

vijos 1243 生产产品 DP + 单调队列优化

LINK 题意:有1个产品,m个步骤编号为1~m.步骤要在n个机器人的手中生产完成.其中,第i个步骤在第j个机器人手中的生产时间给定为$T[i][j]$,切换机器人消耗cost.步骤必须按顺序,同一个机器人不能连续完成超过l个步骤.求完成所有步骤的最短时间是多少.其中$m<=10^5$,$n<=5$,$l<=5*10^4$ 思路:这题用DP考虑易得一个转移方程$dp[i][j]=\min^{i-1}_{v=i-L}{(dp[v][x] + sum[i][j] - sum[v][j]) +

[Vijos 1243]生产产品(单调队列优化Dp)

Description 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器中的任何一台完成,但生产的步骤必须严格按顺序执行.由于这N台机器的性能不同,它们完成每一个步骤的所需时间也不同.机器i完成第j个步骤的时间为T[i,j].把半成品从一台机器上搬到另一台机器上也需要一定的时间K.同时,为了保证安全和产品的质量,每台机器最多只能连续完成产品的L个步骤.也就是说,如果有一台机器连续完

vijos 1243 生产产品

貌似两年前联赛复习的时候就看过这题 然而当时大概看看了 感觉太难 便没有去做 如今再去做的时候 发现其实也并不容易 ------------------------------------------------------------------------- 这题首先是要处理一下不能在同一台机器上工作L个步骤 对于这一点 我们可以构造两个数组 f[i][j]表示在第i台机器上完成了第j个步骤 g[i][j]表示在第i台机器上完成了第j个步骤 且第j-1个步骤不是在第i台机器上完成的 这一个问

vijos P1243 生产产品(单调队列+DP)

P1243生产产品 描述 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产 品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器中的任何一台完成,但生产的步骤必须严格按顺序执行.由于这N 台机器的性能不同,它们完成每一个步骤的所需时间也不同.机器i完成第j个步骤的时间为T[i,j].把半成品从一台机器上搬到另一台机器上也需要一定的 时间K.同时,为了保证安全和产品的质量,每台机器最多只能连续完成产品的L个步骤.也就是说,如果有一台机

Vijos P1243 生产产品 (单调队列优化DP)

题意: 必须严格按顺序执行M个步骤来生产一个产品,每一个步骤都可以在N台机器中的任何一台完成.机器i完成第j个步骤的时间为T[i][j].把半成品从一台机器上搬到另一台机器上也需要一定的时间K.每台机器最多只能连续完成产品的L个步骤.也就是说,如果有一台机器连续完成了产品的L个步骤,下一个步骤就必须换一台机器来完成.问一个产品最短需要多长时间呢?(对于100%的数据,N<=5, L<=50000,M<=100000) 题意: 被高中生虐了~ 题意要求尽量缩短时间来完成一件产品,但是由于需

HDU - 3790 最短路径问题(Dijkstra+优先队列优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3790 题意:中文题(边被赋予两种属性,一种是路径,一种是花费),然后略.(逃...... 今天看了卿学姐的视频,初尝SPFA和Dijkstra. 一个是用队列优化,一个是用优先队列优化.这道题目用这两种方法都可以. dijkstra算法思想(贪心):从距离起点最近的点开始,从这个点遍历一遍它周围的点,进行松弛操作,直到最终点. 整个的算法思想就是贪心,每次都给它形成最短路. 这道题目值得注意的是预处

地铁 Dijkstra(优先队列优化) 湖南省第五届省赛

传送门:地铁 思路:拆点,最短路:拆点比较复杂,所以对边进行最短路,spfa会tle,所以改用Dijkstra(优先队列优化) 模板 /************************************************************** Problem: User: youmi Language: C++ Result: Accepted Time: Memory: *****************************************************

最短路--dijkstra+优先队列优化模板

不写普通模板了,还是需要优先队列优化的昂 1 #include<stdio.h> //基本需要的头文件 2 #include<string.h> 3 #include<queue> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 typedef pair<int,int> pii; 8 const int INF=0x3f3f3f3f; 9 10 11

POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA)

POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA) ACM 题目地址:POJ 3013 题意: 圣诞树是由n个节点和e个边构成的,点编号1-n,树根为编号1,选择一些边,使得所有节点构成一棵树,选择边的代价是(子孙的点的重量)×(这条边的价值).求代价最小多少. 分析: 单看每个点被计算过的代价,很明显就是从根到节点的边的价值.所以这是个简单的单源最短路问题. 不过坑点还是很多的. 点的数量高达5w个,用矩阵存不行,只能用边存. 还有路径和结