/*虽然这暴力剪了又剪 改了又改 还是初始的20分...*/ #include<iostream> #include<cstdio> #include<cstring> #define maxn 2010 using namespace std; int n,sum,c[maxn],ans,p,t1,t2,c1,c2,f[maxn]; void Dfs(int now,int cost) { if(cost>=ans)return; if(now==n){ans=min(ans,cost);return;} int a,b,x=0; for(int i=0;i<=c[now];i++) { b=c[now]-i;a=i; if(a>c[now+t1]-f[now+t1])a=c[now+t1]-f[now+t1]; if(b>c[now+t2]-f[now+t2])b=c[now+t2]-f[now+t2]; if((a&&now+t1>n)||(b&&now+t2>n))continue; f[now+t1]+=a;f[now+t2]+=b; x=max(0,c[now+1]-f[now+1]); Dfs(now+1,cost+x*p+a*c1+b*c2); f[now+t1]-=a;f[now+t2]-=b; } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&c[i]),sum+=c[i]; scanf("%d%d%d%d%d",&p,&t1,&c1,&t2,&c2); ans=sum*p;Dfs(1,c[1]*p); printf("%d ",ans); return 0; }
/* 标签是网络流 然而并不会 贪心的复杂度是 O(Σci)ci为每天的需求 比较大...... 如果暴力的话 每天的状态需要枚举那几个来自慢洗的 那几个来自快洗的 那几个来自买的 复杂度高到上天.... 我们可以从买的角度考虑 枚举一共买多少 尽量先给前面 这样后面可供使用的就多 当买了不够了的话 就用洗出来的补 对于i时刻 显然优先用慢洗出来的补更便宜 慢洗的用完了在用快洗的 这里用快洗的时候要优先使用隔得近的 保证后面的状态可以得到更多的慢洗的 then 就是代码了 */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 2010 using namespace std; int n,p,sum,mxx,c1,c2,t1,t2,c[maxn],Zang[maxn],ans,falg; int cnow,nump,ci,num1,num2; int main() { //freopen("napkin.in","r",stdin); //freopen("napkin.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&c[i]),sum+=c[i],mxx=max(mxx,c[i]); scanf("%d%d%d%d%d",&p,&t1,&c1,&t2,&c2); ans=sum*p; for(int k=sum-1;k>=mxx;k--)//枚举一共买多少 { cnow=k*p;nump=k; for(int i=1;i<=n;i++) { if(nump>=c[i]){nump-=c[i];Zang[i]=c[i];}//前面的优先买 提前拿去洗 更优 else { ci=c[i]-nump;//除了买来的 还需要几个 num1=num2=nump=0; for(int j=1;j<=i-t2;j++)//慢洗的优先 { if(ci>num2) { num2+=Zang[j];Zang[j]=0; if(num2>=ci) { Zang[j]=num2-ci;num2=ci; break; } } } ci-=num2;//出去慢洗的 if(ci)//如果不够 { for(int j=i-t1;j>=1;j--)//快洗先用隔得最近的 { if(ci>num1) { num1+=Zang[j];Zang[j]=0; if(num1>=ci) { Zang[j]=num1-ci;num1=ci; break; } } } } ci-=num1; if(ci){falg=1;break;}//购买量太少而周转不过来时 cnow+=num1*c1+num2*c2;Zang[i]=c[i]; } } if(falg)break; else ans=min(ans,cnow); } printf("%d ",ans); return 0; }