建议评绿或黄(我该at谁)
查看原帖
建议评绿或黄(我该at谁)
642173
KarmaticEnding楼主2024/12/2 10:51

这题并没有题解里面说的繁琐建图,观察到如果两个点在一条直线上,那么 x1y1=x2y2\frac{x_1}{y_1}=\frac{x_2}{y_2},那么 x1gcd(x1,y1)=x2gcd(x2,y2)\frac{x_1}{\gcd(x_1,y_1)}=\frac{x_2}{\gcd(x_2,y_2)},同理 y1gcd(x1,y1)=y2gcd(x2,y2)\frac{y_1}{\gcd(x_1,y_1)}=\frac{y_2}{\gcd(x_2,y_2)},那么只需要对 xgcd(x,y)\frac{x}{\gcd(x,y)}ygcd(x,y)\frac{y}{\gcd(x,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

2024/12/2 10:51
加载中...