这题并没有题解里面说的繁琐建图,观察到如果两个点在一条直线上,那么 y1x1=y2x2,那么 gcd(x1,y1)x1=gcd(x2,y2)x2,同理 gcd(x1,y1)y1=gcd(x2,y2)y2,那么只需要对 gcd(x,y)x 和 gcd(x,y)y 执行哈希,并把哈希值相同的丢到一个 vector 里面排序,再执行分组背包就可以了。
哈希是橙,分组背包是橙,所以这题最高是绿。
代码虽然很长,那是我自己马蜂不好导致的,这题还是很简单的。
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXT=4e4+10,MAXN=256;
int n,T;
struct GOLD{
int xpos,ypos;
int digtim,valu;
}a[MAXN];
vector<GOLD> vec[MAXN*MAXN<<1];
int hs[MAXN];
bool vis_sort[MAXN*MAXN<<1],vis_add[MAXN*MAXN<<1],vis_trans[MAXN*MAXN<<1];
int f[MAXT];
inline int hsh(int x,int y){
return (x+MAXN)*MAXN+y;
}
inline int gcd(int x,int y){
return y?gcd(y,x%y):x;
}
int main(){
scanf("%d%d",&n,&T);
for(int i=1;i<=n;++i){
scanf("%d%d%d%d",&a[i].xpos,&a[i].ypos,&a[i].digtim,&a[i].valu);
hs[i]=hsh(a[i].xpos/gcd(a[i].xpos,a[i].ypos),a[i].ypos/gcd(a[i].xpos,a[i].ypos));
vec[hs[i]].push_back(a[i]);
}
for(int i=1;i<=n;++i){
if(!vis_sort[hs[i]]){
vis_sort[hs[i]]=true;
sort(vec[hs[i]].begin(),vec[hs[i]].end(),[&](GOLD H,GOLD G){return H.xpos==G.xpos?H.ypos<G.ypos:H.xpos<G.xpos;});
}
}
for(int i=1;i<=n;++i){
if(!vis_add[hs[i]]){
vis_add[hs[i]]=true;
for(unsigned long long j=1;j<vec[hs[i]].size();++j){
vec[hs[i]][j].digtim+=vec[hs[i]][j-1].digtim;
vec[hs[i]][j].valu+=vec[hs[i]][j-1].valu;
}
}
}
f[0]=0;
for(int k=1;k<=n;++k){
if(!vis_trans[hs[k]]){
vis_trans[hs[k]]=true;
for(int i=T;i>=0;--i){
for(int j=0;j<vec[hs[k]].size();++j){
if(i-vec[hs[k]][j].digtim>=0){
f[i]=max(f[i],f[i-vec[hs[k]][j].digtim]+vec[hs[k]][j].valu);
}
}
}
}
}
int ans=0;
for(int i=1;i<=T;++i){
ans=max(ans,f[i]);
}
printf("%d",ans);
return 0;
}
有没有好心人帮我at一下管理员qwq