1. 程式人生 > >[Vijos 1243]生產產品(單調隊列優化Dp)

[Vijos 1243]生產產品(單調隊列優化Dp)

lib div solution int 目的 每一個 lan || space

Description

在經過一段時間的經營後,dd_engi的OI商店不滿足於從別的供貨商那裏購買產品放上貨架,而要開始自己生產產品了!產品的生產需要M個步驟,每一個步驟都可以在N臺機器中的任何一臺完成,但生產的步驟必須嚴格按順序執行。由於這N臺機器的性能不同,它們完成每一個步驟的所需時間也不同。機器i完成第j個步驟的時間為T[i,j]。把半成品從一臺機器上搬到另一臺機器上也需要一定的時間K。同時,為了保證安全和產品的質量,每臺機器最多只能連續完成產品的L個步驟。也就是說,如果有一臺機器連續完成了產品的L個步驟,下一個步驟就必須換一臺機器來完成。現在,dd_engi的OI商店有史以來的第一個產品就要開始生產了,那麽最短需要多長時間呢?

某日Azuki.7對躍動說:這樣的題目太簡單,我們把題目的範圍改一改
對於菜鳥躍動來說,這是個很困難的問題,他希望你能幫他解決這個問題

Solution

看了MashiroSky的題解=w=

f[j][i]表示完成了前i個步驟,第i步由j完成,預處理第j個機器完成前i個步驟的時間s[j][i]

考慮樸素的dp能得到轉移方程f[j][i]=min(f[k][l]+s[j][i]-s[j][l]+K)=min(f[k][l]-s[j][l])+s[j][i]+K(l<i i-l<=L)

然後發現f[k][l]-s[j][l]與l有關 與i無關,此處可以單調隊列優化,維護n個單調隊列

就能O(mn2)解決啦

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define N 6
#define M 100005
#define INF 0x3f3f3f3f
using namespace std;
int m,n,k,L,t[N][M],f[N][M],q[N][M],p[N][M],l[N],r[N],ans=INF;
int read()
{
    int x=0,f=1;char c=getchar();
    
while(c<0||c>9){if(c==-)f=-1;c=getchar();} while(c>=0&&c<=9){x=x*10+c-0;c=getchar();} return x*f; } int main() { m=read(),n=read(),k=read(),L=read(); for(int i=1;i<=n;i++) { l[i]=r[i]=1; for(int j=1;j<=m;j++) t[i][j]=read()+t[i][j-1]; } for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { while(l[j]<=r[j]&&q[j][l[j]]<i-L)l[j]++; f[j][i]=t[j][i]+p[j][l[j]]+k; } for(int k=1;k<=n;k++) { for(int j=1;j<=n;j++) { if(k==j)continue; while(l[j]<=r[j]&&p[j][r[j]]>=f[k][i]-t[j][i])r[j]--; q[j][++r[j]]=i; p[j][r[j]]=f[k][i]-t[j][i]; } } } for(int i=1;i<=n;i++)ans=min(f[i][m]-k,ans); printf("%d\n",ans); return 0; }

[Vijos 1243]生產產品(單調隊列優化Dp)