题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6408
刚刚到学校火车坐的想死。。
拜读了大佬的代码,有两个思路上的新理解吧。。
1、还是降维吧,给了一个材料费用一个组装费用。将第i天最小的材料费用计算出来。本来想的是要n^2去计算,后来发现只要和前一天进行比对即可,因为两天如果材料来源相同,差别只在于i-1到i天的存储费用
2、计算某天某材料花费时,用ss表示类似存储费用前缀和一样的东西,在存储的时候减去到当前为止的存储费用,取的时候再加上卖电脑那一天的存储费用,结果就是中间的费用和了
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod 1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=50005;
int c[N],d[N],m[N],p[N],e[N],R[N],E[N];
int n;
LL pin()
{
multiset<pair<LL,int>> w;
LL s=0,ss=0;
LL ans=0;
For(i,0,n-1)
{
w.insert(make_pair(m[i]-ss,p[i]));
s+=p[i]-d[i];
while(!w.empty()&&d[i]>0)
{
auto c=*w.begin();
w.erase(w.begin());
if(c.second<=d[i])
{
ans+=(LL)(c.first+ss)*c.second;
d[i]-=c.second;
}
else
{
ans+=(LL)(c.first+ss)*d[i];
c.second-=d[i];
d[i]=0;
w.insert(c);
}
}
if(d[i])return -1;
ss+=E[i+1];
LL req=s-e[i+1];
s=min(s,(LL)e[i+1]);
while(req>0)
{
auto c=*(--w.end());
w.erase(--w.end());
if(c.second<=req)
req-=c.second;
else
{
c.second-=req;
req=0;
w.insert(c);
}
}
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
For(i,0,n-1)scanf("%d%d%d%d",&c[i],&d[i],&m[i],&p[i]);
For(i,1,n-1)scanf("%d%d%d",&e[i],&R[i],&E[i]);
For(i,1,n-1)
{
c[i]=min(c[i],c[i-1]+R[i]);
m[i]+=c[i];
}
m[0]+=c[0];
printf("%lld\n",pin());
}
return 0;
}