Aizu 1379 Parallel Lines
文章目錄
題目連結:
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1379
https://vjudge.net/contest/270706#problem/B
題意:給了N個點,問能最多能選出幾對直線的斜率相同,斜率可能有多種,點不能重複使用
比賽的時候想把斜率預處理出來,然後列舉能組成這個斜率的直線有多少個
但是後來發現點不能重複使用。。。而這種方法弄出來的點的重複使用了的,所以就不行
然後看題解說直接暴力判斷,我還想說暴力力題啊,不做了不做了,但是仔細想想暴力要怎麼暴力喃?好像我還不怎麼會暴力T_T,還是做一哈算了,結果。。。幸好做了,感覺這道題對我來說其實很有價值~
(一)計算複雜度
首先這個算複雜度的時候我傻逼了,我寫了個dfs發現誒怎麼符合條件的方案怎麼那麼多???
N=4:6種
N=6:90種
N=8:2520種
我覺得不應該是這麼多啊,N=4的時候都只有3種呀
(1,2)(3,4)
(1,3)(2,4)
(1,4)(2,3)
N=4應該只有這三種
應該是有重複的
然後專門寫了個暴力來跑,用的排列來暴力,好像算到12就算不動了T_T
N=4:3種
N=6:15種
N=8:105種
然後用前幾項去OEIS查,發現竟然是個雙階乘的數列,雙階乘我還以為是階乘的階乘勒,結果要麼是偶數的階乘,要麼是奇數的階乘。
後來我反應過來了,上面N=8的時候有重複的是2520種,無重複的是105種是怎麼來的了
每次選兩種:
然後8個點有4對,這4對排列是重複的
因此:
然後驗證其他的,發現是對的
(二)dfs兩重循換變一重
解決了上面的問題我又寫了一發,跑最後一個樣例的時候發現用了12000ms+
看別人的程式碼我驚訝地發現為什麼別人的dfs裡面只有一層迴圈呀???一次選兩個數讓我想怎麼也要寫兩個for迴圈才行呀~
哇,原來別人是這樣的:
首先看當前這個數能不能用
①:要是闊以用,那就用for迴圈再找另一個闊以用的數
②:如果不能用,就直接進入下一層dfs
哇,這樣時間上測出來就直接少了4000ms+
最後統計答案那裡,我開始是用map統計這種斜率的直線的個數來計算,改成兩層for迴圈直接暴力,速度瞬間變成了1000ms+了,快了8倍左右。。。
#include"bits/stdc++.h"
#define out(x) cout<<#x<<"="<<x
#define C(n,m) (m>n?0:(long long)fac[(n)]*invf[(m)]%MOD*invf[(n)-(m)]%MOD)
using namespace std;
typedef long long LL;
const int maxn=1e2+5;
const int MOD=1e9+7;
int FULL,Max;
int a[maxn],t;
struct Point
{
int x,y;
Point() {}
Point(int x,int y):x(x),y(y) {}
};
Point P[maxn];
pair<int,int>Slope[maxn][maxn];//怕用double炸精度啥的,所以用pair來表示斜率
int N;
int f()
{
int res=0;
// map<pair<int,int>,int>Mp;
// for(int i=1; i<N; i+=2)Mp[Slope[a[i]][a[i+1]]]++;
// for(auto i:Mp)
// {
// int n=i.second;
// if(n>=2)res+=n*(n-1)/2;
// }
//for迴圈快8倍
for(int i=1; i<=N; i+=2)
{
for(int j=i+2; j<=N; j+=2)
{
int dx=Slope[a[i]][a[i+1]].first;
int dy=Slope[a[i]][a[i+1]].second;
int tx=Slope[a[j]][a[j+1]].first;
int ty=Slope[a[j]][a[j+1]].second;
if(dx==tx&&dy==ty)res++;
}
}
return res;
}
int cnt;
void dfs(int STA,int now)
{
cnt++;
if(STA==FULL)
{
Max=max(Max,f());
return ;
}
if(STA&(1<<now))dfs(STA,now+1);//如果當前這個不能選,直接進入下一個dfs
else
{
for(int i=1; i<=N; i++)
{
if(now==i)continue;
if(STA&(1<<i))continue;
int sta=STA|(1<<i);
sta|=(1<<now);
a[++t]=now,a[++t]=i;//同時選now和i
dfs(sta,now+1);
t-=2;
}
}
}
clock_t t1,t2;
int main()
{
while(cin>>N)
{
t=Max=FULL=0;
for(int i=1; i<=N; i++)
{
cin>>P[i].x>>P[i].y;
FULL|=(1<<i);
}
for(int i=1; i<=N; i++)//預處理出斜率
{
for(int j=i+1; j<=N; j++)
{
int x=P[i].x-P[j].x;
int y=P[i].y-P[j].y;
if(x==0)y=1;
else if(y==0)x=1;
else
{
int d=__gcd(x,y);
x/=d,y/=d;
}
Slope[i][j]=Slope[j][i]=make_pair(x,y);
}
}
t1=clock();
cnt=0;
dfs(0,1);
// cout<<"cnt="<<cnt<<endl;
t2=clock();
// cout<<"time="<<t2-t1<<endl;
cout<<Max<<endl;
}
}
/*
16
327 449
-509 761
-553 515
360 948
147 877
-694 468
241 320
463 -753
-206 -991
473 -738
-156 -916
-215 54
-112 -476
-452 780
-18 -335
-146 77
*/