版权声明:虽然本蒟蒻很菜,但各位dalao转载请注明出处谢谢。 https://blog.csdn.net/xuxiayang/article/details/85014698
题目
思路
其实就是一个多重背包
二进制拆分跑得比单调队列优化还快。。。
代码(二进制优化)
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;int n,m,tmp,num;
int a,b[211],c[211],d[211];
int w[10009],p[10009],f[100009];
inline char Getchar()
{
static char buf[100000],*p1=buf+100000,*pend=buf+100000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,100000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline long long read()
{
char c;int d=1;long long f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register long long x)
{
if(x<0)write(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
inline void cal(register int gs,register int wx,register int px)
{
for(int i=1;i<=gs;i<<=1)
{
w[++num]=wx*i;p[num]=px*i;
gs-=i;
}
if(gs){w[++num]=gs*wx;p[num]=px*gs;}
return;
}
signed main()
{
freopen("1.txt","r",stdin);
memset(f,0xcf,sizeof(f));f[0]=0;
n=read();
for(register int i=1;i<=n;i++)
{
a=read();b[i]=read();c[i]=read();d[i]=read();
b[i]-=a;tmp+=a*d[i];m-=a*c[i];
}
for(int i=1;i<=n;i++)cal(b[i],c[i],d[i]);
for(register int i=1;i<=num;i++) for(register int j=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+p[i]);
write(f[m]+tmp);
}
代码(单调队列)
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;int n,m,tmp,num,t,i,j,k;
int a,w[211],c[211],v[211],f[2][100009],l,r;
inline char Getchar()
{
static char buf[100000],*p1=buf+100000,*pend=buf+100000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,100000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline long long read()
{
char c;int d=1;long long f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register long long x)
{
if(x<0)putchar(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
int q[211],sd;
inline int calc(register int k){return f[!t][j+k*w[i]]-k*v[i];}
signed main()
{
freopen("1.txt","r",stdin);
n=read();
for(register int i=1;i<=n;i++)
{
a=read();c[i]=read();w[i]=read();v[i]=read();
c[i]-=a;tmp+=a*v[i];m-=a*w[i];
}
for(register int i=1;i<=m;i++) f[0][i]=-1e9;
for(i=1;i<=n;i++)
{
t=!t;sd+=c[i]*w[i];if(sd>m)sd=m;
for(j=0;j<w[i];j++)
{
l=1;r=0;
int maxp=(sd-j)/w[i];
for(k=0;k<=maxp;k++)
{
while(l<=r&&calc(q[r])<calc(k))r--;q[++r]=k;
if(q[l]+c[i]<k)l++;
f[t][k*w[i]+j]=f[!t][q[l]*w[i]+j]+(k-q[l])*v[i];
}
}
}
write(f[t][m]+tmp);
}
代码(STL)
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;int n,m,tmp,num,t,i,j,k;
int a,w[211],c[211],v[211],f[2][100009],l,r;
inline char Getchar()
{
static char buf[100000],*p1=buf+100000,*pend=buf+100000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,100000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline long long read()
{
char c;int d=1;long long f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register long long x)
{
if(x<0)putchar(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
deque<int>q;
int sd;
inline int calc(register int k){return f[!t][j+k*w[i]]-k*v[i];}
signed main()
{
n=read();
for(register int i=1;i<=n;i++)
{
a=read();c[i]=read();w[i]=read();v[i]=read();
c[i]-=a;tmp+=a*v[i];m-=a*w[i];
}
for(register int i=1;i<=m;i++) f[0][i]=-1e9;
for(i=1;i<=n;i++)
{
t=!t;sd+=c[i]*w[i];if(sd>m)sd=m;
for(j=0;j<w[i];j++)
{
while(q.size())q.pop_front();
l=1;r=0;
int maxp=(sd-j)/w[i];
for(k=0;k<=maxp;k++)
{
while(q.size()&&calc(q.back())<calc(k)) q.pop_back();q.push_back(k);
if(q.front()+c[i]<k) q.pop_front();
f[t][k*w[i]+j]=f[!t][q.front()*w[i]+j]+(k-q.front())*v[i];
}
}
}
write(f[t][m]+tmp);
}