题面
题意
平面上有n个点,两两之间连线后,求一共能构成多少个五角星.
做法
首先可以将五角星看作是有5个点的凸包,也就是5个极角排序后递增的向量首尾相接后得到的图形.
因此可以记
d
p
[
x
]
[
y
]
[
i
]
dp[x][y][i]
dp[x][y][i]表示从点x到点y经过i个线段的方案数,对所有向量(一个线段可以看作是两个向量)进行极角排序后,依次来更新dp值,这样
∑
i
=
1
n
d
p
[
i
]
[
i
]
[
5
]
\sum_{i=1}^ndp[i][i][5]
∑i=1ndp[i][i][5]就是答案.
代码
#include<bits/stdc++.h>
#define ll long long
#define db double
#define N 310
using namespace std;
ll n,xx,ans,dp[N][N][6];
db x[N],y[N];
struct Xd
{
ll u,v;
db jd;
bool operator < (const Xd &u) const{return jd<u.jd;}
}xd[N*N];
int main()
{
ll i,j,k;
cin>>n;
for(i=1;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==j) continue;
xd[++xx]=(Xd){i,j,atan2(y[j]-y[i],x[j]-x[i])};
}
}
sort(xd+1,xd+xx+1);
for(i=1;i<=xx;i++)
{
dp[xd[i].u][xd[i].v][1]=1;
for(j=1;j<=n;j++)
{
for(k=2;k<=5;k++)
{
dp[j][xd[i].v][k]+=dp[j][xd[i].u][k-1];
}
}
}
for(i=1;i<=n;i++) ans+=dp[i][i][5];
cout<<ans;
}