P2848 [USACO16DEC] Cow Checklist G 题解
思路:
很明显这是一道 DP,首先我们先来分析一下这道题:
题目让我做什么:
穷举所有行走路线。
以什么为对象划分顺序,分几步完成,每一步做什么(决策):
以步数划分顺序,分成
状态是什么,状态就是整个问题的描述:
这里不需要时间,因为时间一定等于
现在的方程
可以考虑往状态里增加一维,就是
状态转移方程:
我们来想一下最后的方程,有了方程就很好写代码啦,我觉得方程就是去掉最后一步的状态+最后一步的状态(大多数啊),想一想这两个状态上一步是由谁推出来的,先来看
小知识:
ok,现在就差两个方程的最后一步状态了,我们需要知道一个原理,运用勾股定理可知:在平面直角坐标系中两个点的距离的平方
dis1[i]=pow(H[i].x-H[i+1].x,2)+pow(H[i].y-H[i+1].y,2);
dis2[i][j]=pow(H[i].x-G[j].x,2)+pow(H[i].y-G[j].y,2);
dis3[i]=pow(G[i].x-G[i+1].x,2)+pow(G[i].y-G[i+1].y,2);
现在我觉得方程你就能看懂啦ヾ(❀^ω^)ノ゙。
f[i][j][0]=min(f[i][j][0],min(f[i-1][j][0]+dis1[i-1],f[i-1][j][1]+dis2[i][j]));
f[i][j][1]=min(f[i][j][1],min(f[i][j-1][1]+dis3[j-1],f[i][j-1][0]+dis2[i][j]));
Code:
#include<bits/stdc++.h>//可爱的懒人头文件
using namespace std;
int n,m;
long long f[1009][1009][2],dis1[1009],dis3[1009],dis2[1009][1009];
struct node
{
int x,y;
}H[1009],G[1009];//写一个结构体
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>H[i].x>>H[i].y;//读入H第i个点的坐标
}
for(int i=1;i<=m;i++)
{
cin>>G[i].x>>G[i].y;//读入G第i个点的坐标
}
for(int i=1;i<n;i++)
{
dis1[i]=pow(H[i].x-H[i+1].x,2)+pow(H[i].y-H[i+1].y,2);
}
for(int i=1;i<m;i++)
{
dis3[i]=pow(G[i].x-G[i+1].x,2)+pow(G[i].y-G[i+1].y,2);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
dis2[i][j]=pow(H[i].x-G[j].x,2)+pow(H[i].y-G[j].y,2);
}
}
memset(f,0x7f,sizeof(f));//初始化无穷大
f[1][0][0]=0;//从题目可以看出农夫约翰最开始位于H序列的第一个点,所以第一维数组就是1,G序列一个点也没走所以第二维就是0,题目说农夫约翰在H结束所以第三维就是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]+dis1[i-1],f[i-1][j][1]+dis2[i][j]));
if(j>0)f[i][j][1]=min(f[i][j][1],min(f[i][j-1][1]+dis3[j-1],f[i][j-1][0]+dis2[i][j]));//DP方程
}
}
cout<<f[n][m][0];
return 0;
}