[usaco]2008 Dec Largetst Fence最大のフェンス2‖dp
2164 ワード
元サイトは多分もう上がらない・・・
平面上のn点からなる頂点数が最も多い凸多角形を求める.n<=250.
凸包の左下角を列挙するたびに(Grahamを参照して凸包を求めるときの左下角)を考慮し、Grahamのように現在の左下角に対して他の点を極角ソートします.dp,dp[i][j]は現在のエッジがiからjの最大点であることを示し,以下のような遷移を得る.
これがn^4ですが、どうやって最適化しますか?f[i]がdp[][i]の最大値であることを記録することができ,これにより列挙kのnを省くことができ,n^3アルゴリズムが得られる.列挙kの過程を省くのでcheckはどうしますか?各セグメントを前処理し、セグメントを極角でソートすればいいです.
平面上のn点からなる頂点数が最も多い凸多角形を求める.n<=250.
凸包の左下角を列挙するたびに(Grahamを参照して凸包を求めるときの左下角)を考慮し、Grahamのように現在の左下角に対して他の点を極角ソートします.dp,dp[i][j]は現在のエッジがiからjの最大点であることを示し,以下のような遷移を得る.
for (int i=1;i<=n;i++)
if (x!=i) dp[x][i]=1;
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
for (int k=1;k
これがn^4ですが、どうやって最適化しますか?f[i]がdp[][i]の最大値であることを記録することができ,これにより列挙kのnを省くことができ,n^3アルゴリズムが得られる.列挙kの過程を省くのでcheckはどうしますか?各セグメントを前処理し、セグメントを極角でソートすればいいです.
#include
#include
#include
#define N 300
using namespace std;
int n,q[N],f[N],dp[N][N],num,ans;
struct hhh
{
int x,y;
hhh() : x(0),y(0) {}
hhh(int _x,int _y) : x(_x),y(_y) {}
hhh operator - (const hhh &b) const
{
return hhh(x-b.x,y-b.y);
}
int operator * (const hhh &b) const
{
return x*b.y-y*b.x;
}
}a[N];
struct hh
{
hhh qwq;
int a,b;
bool operator < (const hh &b) const
{
return qwq*b.qwq<0;
}
}v[N*N];
int read()
{
int ans=0,fu=1;
char j=getchar();
for (;j'9';j=getchar()) if (j=='-') fu=-1;
for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
return ans*fu;
}
int check(int x)
{
memset(f,128,sizeof(f));
memset(dp,0,sizeof(dp));
f[x]=0;
int QwQ=0;
for (int i=1;i<=num;i++)
{
dp[v[i].a][v[i].b]=max(dp[v[i].a][v[i].b],f[v[i].a]+1);
if (v[i].b!=x) f[v[i].b]=max(f[v[i].b],f[v[i].a]+1);
}
for (int i=1;i<=n;i++)
QwQ=max(QwQ,dp[i][x]);
return QwQ;
}
int main()
{
freopen("dot.in","r",stdin);
freopen("dot.out","w",stdout);
n=read();
for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (i!=j)
v[++num].qwq=a[i]-a[j],v[num].a=i,v[num].b=j;
sort(v+1,v+num+1);
for (int i=1;i<=n;i++)
ans=max(ans,check(i));
printf("%d
",ans);
return 0;
}