Why Did the Cow Cross the Road I G

W h y   D i d   t h e   C o w   C r o s s   t h e   R o a d   I   G Why\ Did\ the\ Cow\ Cross\ the\ Road\ I\ G Why Did the Cow Cross the Road I G

题目链接: l u o g u   P 3659 luogu\ P3659 luogu P3659 / j z o j   6688 jzoj\ 6688 jzoj 6688 / nowcoder 24072 ⁡ \operatorname{nowcoder\ 24072} nowcoder 24072

题目

奶牛们为什么要穿马路?一个原因只是因为 F J FJ FJ的牧场的路实在是太多了,使得奶牛们每天不得不穿梭在许许多多的马路中央

F J FJ FJ的牧场可以看作是一块 N × N N\times N N×N 的田地 ( 3 ≤ N ≤ 100 ) (3\le N\le 100) 3N100 N − 1 N-1 N1 条南北向的道路和 N − 1 N-1 N1 条东西向的道路贯穿整个牧场,同时是每块田野的分界线。牧场的最外面是一圈高大的栅栏以防止奶牛离开牧场。 B e s s i e Bessie Bessie只要穿过分离两块田野的道路,就可以从任何田野移动到与其相邻的田野里去(北,东,南或西)。当然, B e s s i e Bessie Bessie穿过每一条马路都是需要TT 时间的。 ( 0 ≤ T ≤ 1 , 000 , 000 ) (0\le T\le 1,000,000) 0T1,000,000

有一天, F J FJ FJ邀请 B e s s i e Bessie Bessie来他家下棋, B e s s i e Bessie Bessie从牧场的西北角出发, F J FJ FJ的家在牧场的东南角。因为 B e s s i e Bessie Bessie在中途可能会饿,所以她每走过三块田野就要停下来,享用她所在田野上的新鲜的牧草(不包括 B e s s i e Bessie Bessie的出发点,但是可能会包括终点 F J FJ FJ的家),牧场上有些田野的牧草长得比其他地方茂盛,所以 B e s s i e Bessie Bessie对应的停留时间也会变长。

请帮帮 B e s s i e Bessie Bessie计算出她走到 F J FJ FJ家的最短时间。

输入

接下来 N N N 行,每行 N N N 个数表示每块田野 B e s s i e Bessie Bessie需要停留的时间(每块最多不超过 100 , 000 100,000 100,000),第一行的第一块田野是牧场的西北角

输出

一行一个整数表示 B e s s i e Bessie Bessie走到 F J FJ FJ家的最短时间

样例输入

4 2
30 92 36 10
38 85 60 16
41 13 5 68
20 97 13 80

样例输出

31

样例解释

对于样例, B e s s i e Bessie Bessie先向东走过了三块田野(在 “ 10 ” “10” 10停留),再向南走两步,又向西走了一步(在 “ 5 ” “5” 5停留),最后向南走一步,再向东走一步到达 F J FJ FJ的家(不用停留),总共时间是 15 15 15(停留时间)+ 16 16 16(穿马路时间)= 31 31 31

思路

这道题其实就是一道最短路。

因为题目说每走 3 3 3部就要吃草,那我们就让它三步三步的走,把从一个点走三步可以走到的地方连起来就完事了。
但是,都最后的时候不一定走了三步,有可能最后只走了一两步就走到了,这样就不用吃草,只用加上走路的时间,那到最后一步的时候我们就判断一下从哪里走到终点最省时间,就可以了。

具体看代码吧。

代码

#include<queue>
#include<cstdio>
#include<cstring>

using namespace std;

struct node {
	int x, y;
};
int n, t, a[101][101], dis[101][101], ans;
bool in[101][101];
int dx[16] = {0, 0, 3, -3, 1, 1, 2, 2, -1, -1, -2, -2, 0, 0, 1, -1};
int dy[16] = {3, -3, 0, 0, 2, -2, 1, -1, 2, -2, 1, -1, 1, -1, 0, 0};

bool ch(int x, int y) {
	if (x < 1 || y < 1 || x > n || y > n) return 0;
	return 1;
}

void spfa(int x, int y) {//最短路
	queue<node>q;
	q.push((node){x, y});
	memset(dis, 0x7f, sizeof(dis));
	dis[x][y] = 0;
	in[x][y] = 1;
	while (!q.empty()) {
		node now = q.front();
		q.pop();
		in[now.x][now.y] = 0;
		for (int i = 0; i < 16; i++) {
			int tx = now.x + dx[i], ty = now.y + dy[i];
			if (ch(tx, ty) && dis[now.x][now.y] + a[tx][ty] + 3 * t < dis[tx][ty]) {//记得要加上走路的时间
				dis[tx][ty] = dis[now.x][now.y] + a[tx][ty] + 3 * t;
				if (!in[tx][ty]) {
					in[tx][ty] = 1;
					q.push((node){tx, ty});
				}
			}
		}
	}
}

int main() {
//	freopen("visitfj.in", "r", stdin);
//	freopen("visitfj.out", "w", stdout);
	
	scanf("%d %d", &n, &t);//读入
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			scanf("%d", &a[i][j]);//读入
	
	spfa(1, 1);//最短路
	
	ans = min(dis[n][n], dis[n - 1][n] + t);//租后一步是怎么走到终点的(指不用吃草的时候)
	ans = min(ans, dis[n][n - 1] + t);
	ans = min(ans, dis[n - 2][n] + t * 2);
	ans = min(ans, dis[n][n - 2] + t * 2);
	ans = min(ans, dis[n - 1][n - 1] + t * 2);
	
	printf("%d", ans);//输出
	
//	fclose(stdin);
//	fclose(stdout);
	
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值