题目大意
每天,农夫约翰走过他的牧场,检查他的每头奶牛的存在感。在他的农场,他有两个品种的牛,Holsteins和Guernseys。
他的H Holsteins方便地编号为1…H,并且他的G Guernseys方便地编号为1…G(1≤H≤1000,1≤G≤1000)。每个牛位于2D平面中的点(不一定是不同的)。
农夫约翰从Holsteins 1出发,在Holsteins H结束。他想要沿途参观每头牛,为了方便保持他到目前为止访问的牛的清单,他想按他们的编号顺序访问Holsteins和Guernseys。
在他访问的所有 H+G 头牛的序列中,Holsteins编号为1…H应该显示为(不一定是连续的)子序列,对于Guernseys也相同。
换句话说,所有H+G牛的序列应该通过将编号为1…H的Holsteins列表与编号为1…G的Guernseys列表交错形成。
当FJ从一头母牛移动到另一头母牛,行进距离为DD时,他消耗D^2D2能量。请帮助他确定访问所有奶牛所需的最低能量。
题目分析
很明显,看到题与数据范围,可以想到一个DP, 令 f[i][j] 为访问到 Gi, Hj 所消耗的最低能量,
然而,我们会发现不确定党建到底是在 Gi 还是 Hj ,所以我们再加一维状态 0/1 来表示当前实在 Gi 还是 Hj
然后直接 O( N^2 ) dp即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int MAXN=1e3+10; 5 const ll Inf=1e18+7; 6 struct Node{ 7 int x,y; 8 }a[MAXN<<1]; 9 10 int n,m; 11 ll dis[MAXN<<1][MAXN<<1]; 12 ll f[MAXN][MAXN][2]; 13 int main(){ 14 scanf("%d%d",&n,&m); 15 for(int i=1;i<=n+m;++i) 16 scanf("%d%d",&a[i].x,&a[i].y); 17 for(int i=1;i<=n+m;++i) 18 for(int j=1;j<=n+m;++j) 19 dis[i][j]=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y); 20 for(int i=0;i<=n;++i) 21 for(int j=0;j<=m;++j) 22 for(int k=0;k<=1;++k) 23 f[i][j][k]=Inf; 24 f[1][0][0]=0; 25 for(int i=1;i<=n;++i) 26 for(int j=0;j<=m;++j){ 27 f[i][j][0]=min(f[i][j][0],min(f[i-1][j][0]+dis[i-1][i],f[i-1][j][1]+dis[i][n+j])); 28 if(j) f[i][j][1]=min(f[i][j][1],min(f[i][j-1][0]+dis[i][n+j],f[i][j-1][1]+dis[n+j-1][n+j])); 29 } 30 printf("%lld\n",f[n][m][0]); 31 return 0; 32 }