题解 P3961 【[TJOI2013]黄金矿工】
这题还行吧,就难度而言emmm,其实这题首先用到了笛卡尔坐标系求斜率,看看是不是一条线上的(上过初中的都知道),然后呢在下面的金子肯定是被后挖到的,那么挖这块金子的前提,就是必须得把上面的都挖完,那么很明显这就是一个依赖性的背包问题了,相关题目详见noip2006金明的预算方案。。。。emmm,直接上代码吧
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct edge{
int x,y,t,v;
double b;
}e[2005];
bool cmp(edge x,edge y){
if(x.b==y.b) return x.y<y.y;
return x.b<y.b;
}
int n,T,cnt,js[2005];int v[2005][2005],t[2005][2005],f[40005];
int main(){
memset(js,0,sizeof(js));
scanf("%d%d",&n,&T);
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].t,&e[i].v);
e[i].b=e[i].y*1.0/(e[i].x*1.0);
}
sort(e+1,e+1+n,cmp);
for(int i=1;i<=n;i++){
if(e[i].b!=e[i-1].b||i==1)
++cnt;
if(js[cnt]==0){
v[cnt][++js[cnt]]=e[i].v;
t[cnt][js[cnt]]=e[i].t;
}
else{
++js[cnt];
v[cnt][js[cnt]]=v[cnt][js[cnt]-1]+e[i].v,t[cnt][js[cnt]]=t[cnt][js[cnt]-1]+e[i].t;
}
}
for(int i=1;i<=cnt;i++)
for(int j=T;j>=t[i][1];j--){
int maxn=f[j];
for(int k=1;k<=js[i];k++){
if(j>=t[i][k])
maxn=max(maxn,f[j-t[i][k]]+v[i][k]);
}
f[j]=maxn;
}
//for(int i=1;i<=cnt;i++)
// for(int j=1;j<=js[i];j++)
// printf("%d %d %d %d \n",i,j,t[i][j],v[i][j]);
printf("%d",f[T]);
return 0;
}
求审核大大给过,毕竟暂时只有我这么一篇题解
哪里不理解可以问我
距离NOIp2018还有99天,共勉!