题面:https://ac.nowcoder.com/acm/contest/33190/A
分析 : 因为是求最优化问题,应会想到DP和贪心
然而贪心并不可取,不可以只先走较长的边(的二长的边距离其 他点很远)
故
我们可以设
d
p
i
,
j
dp_{i,j}
dpi,j为从
i
i
i开始距离为
j
j
j时能得到的最多食物
可是在题目中
(
0
<
N
<
2001
)
(0<N<2001)
(0<N<2001) 而时间复杂度为
O
(
n
3
)
O(n^3)
O(n3),空间复杂度为
O
(
n
4
)
O(n^4)
O(n4),显然不可取
实际上,我们可以设
d
p
i
dp_i
dpi为到
i
i
i点时能得到的最多食物
so,状态转移方程便为
d
p
i
=
m
a
x
(
d
p
i
,
d
p
所有合法的起点
j
+
1
)
dp_i=max(dp_i,dp_{所有合法的起点j}+1)
dpi=max(dpi,dp所有合法的起点j+1)
现在,时间复杂度便只为
O
(
n
2
)
O(n^2)
O(n2),空间复杂度为
O
(
n
2
)
O(n^2)
O(n2),可以通过这道题了
(对于转移时的存储,见代码)
代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int MXN=2007;
struct Edge{
int x,y;
LL w;
};
Edge p[MXN*MXN];
int x[MXN],y[MXN];
int dp[MXN];
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}
bool cmp(Edge xx,Edge yy){
return xx.w>yy.w;
}
int tp[MXN*MXN],top,V[MXN*MXN];
int main(){
int i,j,k,n,len,res;
LL v;
memset(dp,200,sizeof(dp));
n=read();
for(i=1;i<=n;i++){
x[i]=read(); y[i]=read();
}
dp[0]=0;
len=0; res=0; top=0;
for(i=0;i<=n;i++){
for(j=i+1;j<=n;j++){
v=1ll*(x[i]-x[j])*(x[i]-x[j])+1ll*(y[i]-y[j])*(y[i]-y[j]);
len++;
p[len].w=v;
p[len].x=i; p[len].y=j;
len++;
p[len].w=v;
p[len].x=j; p[len].y=i;
}
}
sort(p+1,p+1+len,cmp);
for(i=1;i<=len;i=j+1){
j=i;
while((j<len)&&(p[j+1].w==p[j].w)){
++j;
}
top=0;
for(;i<=j;i++){
if(p[i].y){
tp[++top]=p[i].y;
V[top]=dp[p[i].x];
}
}
while(top){
dp[tp[top]]=max(dp[tp[top]],V[top]+1);
--top;
}
}
for(i=0;i<=n;i++){
res=max(res,dp[i]);
}
cout<<res<<"\n";
}