[Vijos 1243]生產產品(單調隊列優化Dp)
阿新 • • 發佈:2017-07-14
lib div solution int 目的 每一個 lan || space
某日Azuki.7對躍動說:這樣的題目太簡單,我們把題目的範圍改一改
對於菜鳥躍動來說,這是個很困難的問題,他希望你能幫他解決這個問題
Description
在經過一段時間的經營後,dd_engi的OI商店不滿足於從別的供貨商那裏購買產品放上貨架,而要開始自己生產產品了!產品的生產需要M個步驟,每一個步驟都可以在N臺機器中的任何一臺完成,但生產的步驟必須嚴格按順序執行。由於這N臺機器的性能不同,它們完成每一個步驟的所需時間也不同。機器i完成第j個步驟的時間為T[i,j]。把半成品從一臺機器上搬到另一臺機器上也需要一定的時間K。同時,為了保證安全和產品的質量,每臺機器最多只能連續完成產品的L個步驟。也就是說,如果有一臺機器連續完成了產品的L個步驟,下一個步驟就必須換一臺機器來完成。現在,dd_engi的OI商店有史以來的第一個產品就要開始生產了,那麽最短需要多長時間呢?
對於菜鳥躍動來說,這是個很困難的問題,他希望你能幫他解決這個問題
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)