题目描述
输入描述
输出描述
输入样例
2
2
1 1 2 2
0 0 2 3
3
1 1 2 2
1 1 2 2
3 2 5 4
输出样例
0
1
0
0
0
看到 Alice 和 Bob 肌肉反射以为又是一道博弈题,但其实考的是斜率和找规律相关。由题意可得,Alice 的最优策略是选出 k 条斜率尽可能不同的直线,而 Bob 的最优策略是避开斜率出现次数最多的直线,因此可考虑用 pair 将每条直线的斜率都进行标记,同时统计出现过的不同的斜率个数。
将斜率个数定义为 i,不难发现:
当 k ≤ i 时,共有 k − 1 条线相交,
而 i < k ≤ 2i 时,共有 k - 2 条线相交,
……
由此可推出 k 与 i 的关系
不知道为什么总是wa的代码(留给以后解决)
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
typedef pair<int,int> p;
const int N=1e6+10;
p a[N];
int abs(int x){
if(x>=0)
return x;
else
return -x;
}
int gcd(int a,int b){
if(b==0)
return a;
else
return gcd(b,a%b);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,x1,y1,x2,y2,dx,dy,ans=0,res=0;
double k;
map<p,int> mp;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
dx=x2-x1;
dy=y2-y1;
if(dx==0)
dy=1;
else if(dy==0)
dx=1;
else{
if(dx<0)
dx=-dx,dy=-dy;
int d=gcd(abs(dx),abs(dy));
dx/=d,dy/=d;//约分
}
if(mp[p(dx,dy)]==0){
p(dx,dy);
mp[p(dx,dy)]=1;
ans++;
}
}
for(int i=1;i<=n;i++){
res=0;
int a=i/ans;
if(i%ans!=0)
a++;
if(i-a>=0)
res=res+i-a;
cout<<res<<endl;
}
}
}
标准题解
#include <iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> p;
const int N=1e6+10;
p a[N];
int n,i,f[N],j,k;
int abs(int x){
if(x>=0)
return x;
else
return -x;
}
int gcd(int a,int b){
if(b==0)
return a;
else
return gcd(b,a%b);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(i=1;i<=n;i++){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int dx=x2-x1,dy=y2-y1;
if(dx==0)//垂直
dy=1;
else if(dy==0)//水平
dx=1;
else{
if(dx<0)
dx=-dx,dy=-dy;
int d=gcd(abs(dx),abs(dy));
dx/=d,dy/=d;//约分
}
a[i]=p(dx,dy);
}
sort(a+1,a+n+1);
for(i=1;i<=n;i++)f[i]=0;
for(i=1;i<=n;i=j){
for(j=i;j<=n&&a[i]==a[j];j++);
for(k=1;k<=j-i;k++)
f[k]++;
}
for(i=j=1;i<=n;i++){
while(!f[j])
j++;
f[j]--;
printf("%d\n",i-j);
}
}
}