Cow Checklist

【Description】
Every day, Farmer John walks through his pasture to check on the well-being of each of his cows. On his farm he has two breeds of cows, Holsteins and Guernseys. His H Holsteins are conveniently numbered 1…H, and his G Guernseys are conveniently numbered 1…G (1≤H≤1000,1≤G≤1000). Each cow is located at a point in the 2D plane (not necessarily distinct).
Farmer John starts his tour at Holstein 1, and ends at Holstein H. He wants to visit each cow along the way, and for convenience in maintaining his checklist of cows visited so far, he wants to visit the Holsteins and Guernseys in the order in which they are numbered. In the sequence of all H+G cows he visits, the Holsteins numbered 1…H should appear as a (not necessarily contiguous) subsequence, and likewise for the Guernseys. Otherwise stated, the sequence of all H+G cows should be formed by interleaving the list of Holsteins numbered 1…H with the list of Guernseys numbered 1…G.
When FJ moves from one cow to another cow traveling a distance of D, he expends D^2 energy. Please help him determine the minimum amount of energy required to visit all his cows according to a tour as described above.
【INPUT FORMAT】
The first line of input contains H and G, separated by a space.
The next H lines contain the x and y coordinates of the H Holsteins, and the next G lines after that contain coordinates of the Guernseys. Each coordinate is an integer in the range 0…1000.
【OUTPUT FORMAT】
Write a single line of output, giving the minimum energy required for FJ’s tour of all the cows.
【SAMPLE INPUT】
3 2
0 0
1 0
2 0
0 3
1 3
【SAMPLE OUTPUT】
20
【分析】
(为书写方便令H=Holsteins,G=Guernseys)
不难看出这是一个DP问题。
令f[i,j,k]表示已经到达第i头H奶牛,第j头G奶牛,当前在k奶牛(k=0表示在H奶牛,反之为G奶牛)。
预处理出dis[i,j]表示第i头奶牛到第j头奶牛的距离。
对于f[i,j,0],不难想出它只能由两种状态转来:到达第i-1头H奶牛,第1~m头G奶牛,当前在第i-1头H奶牛;到达第i-1头H奶牛,第j头G奶牛,当前在第j头G奶牛。状态转移方程不难得出。
对于f[i,j,1],也是两种状态:到达第i头H奶牛,第j-1头G奶牛,当前在H奶牛或G奶牛。状态转移方程稍复杂,但也不算难。
剩下的就是细节处理了。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=2010;//坑点,我在这里坑了4次才发现问题,1000不够的
struct cow{
    int x,y;
}s[maxn];
typedef long long ll;//坑点,要用long long
int n,m,dis[maxn][maxn];
ll f[maxn][maxn][2];
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d%d",&s[i].x,&s[i].y);
    for (int i=1;i<=m;i++) scanf("%d%d",&s[i+n].x,&s[i+n].y);
    for (int i=1;i<=n+m;i++) 
        for (int j=1;j<=n+m;j++)
            dis[i][j]=(s[i].x-s[j].x)*(s[i].x-s[j].x)+(s[i].y-s[j].y)*(s[i].y-s[j].y);
    for (int i=0;i<=n;i++) for (int j=0;j<=m;j++) for (int k=0;k<=1;k++) f[i][j][k]=1LL<<50;//坑点,初始值不太好赋
    f[1][0][0]=0;
    for (int i=1;i<=n;i++)
        for (int j=0;j<=m;j++){
        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[n+j][i]));
        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]));//坑点,只有j不为0才能接着做下去
    }
    printf("%lld\n",f[n][m][0]);
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值