USACO 2016 December Contest Gold T2: Cow Checklist

题目大意

每天,农夫约翰走过他的牧场,检查他的每头奶牛的存在感。在他的农场,他有两个品种的牛,Holsteins和Guernseys。

他的H Holsteins方便地编号为1H,并且他的G Guernseys方便地编号为1G(1H1000,1G1000)。每个牛位于2D平面中的点(不一定是不同的)。

农夫约翰从Holsteins 1出发,在Holsteins H结束。他想要沿途参观每头牛,为了方便保持他到目前为止访问的牛的清单,他想按他们的编号顺序访问Holsteins和Guernseys。

在他访问的所有 H+G 头牛的序列中,Holsteins编号为1H应该显示为(不一定是连续的)子序列,对于Guernseys也相同。

换句话说,所有H+G牛的序列应该通过将编号为1H的Holsteins列表与编号为1G的Guernseys列表交错形成。

当FJ从一头母牛移动到另一头母牛,行进距离为DD时,他消耗D^2D2能量。请帮助他确定访问所有奶牛所需的最低能量。

 

题目分析

很明显,看到题与数据范围,可以想到一个DP, 令 f[i][j] 为访问到 Gi, Hj 所消耗的最低能量,

然而,我们会发现不确定党建到底是在 G还是 Hj ,所以我们再加一维状态 0/1 来表示当前实在 G还是 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 }

 

转载于:https://www.cnblogs.com/LI-dox/p/11219409.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值