洛谷P4431

本文介绍了一种解决在矩形草坪上使用割草机割草问题的算法,目标是在割完整个草坪的同时,使割草机转弯次数最少。通过分析不同情况下的最优策略,文章给出了一个简单的数学公式来直接计算最小转弯次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意翻译

题目大意:

给定一个nm的矩阵,每次你可以选择前进一格或转弯(90度),求在不出这个矩阵的情况下遍历全部格点所需最少转弯次数。有多组数据

输入格式:

第一行一个整数k,表示数据组数

以下k行,每行两个整数n,m,表示矩阵大小

输出格式:

输出一个整数,即最少转弯次数

感谢@守望 提供翻译

题目描述

Mirko wants to buy land on which he will build a house for his family. So far, he’s seen K pieces of land. Each of them is in the shape of a rectangle and we can think of it as a matrix with N rows and M columns, N × M fields in total.

Mirko is aware that, before construction begins, the property needs to be regularly maintained and the lawn needs to be mowed. Because of this, Mirko bought a lawn mower. In order to mow the entire lawn of N rows and M columns, he needs to go over each field at least once. He can start from any field facing one of the four main directions (up, down, left, and right). His lawn mower can only go forwards (to the adjacent field facing the current direction) or make a 90 degree turn. Additionally, because of his own safety, Mirko can only use the lawn mower on his land, so he cannot leave the matrix.

Since making the lawn mower turn isn’t simple, Mirko wants to mow the lawn with the minimal amount of turns. For each piece of land he saw so far, Mirko wants to know the minimal number of turns he can make so that the entire lawn is mowed. Help Mirko solve this problem.

输入输出格式

输入格式:

 

The first line of input contains the positive integer K (1 ≤ K ≤ 50 000), the number from the task.

Each of the following K lines contains two positive integers N and M (1 ≤ N, M ≤ 1 000 000), the numbers from the task.

 

输出格式:

 

For each piece of land Mirko saw so far, output in a separate line the minimal amount of turns he can take so that the entire lawn is mowed.

 

输入输出样例

输入样例#1: 复制
2
1 10
10 1
输出样例#1: 复制
0
0
输入样例#2: 复制
3
1 1
3 3
3 4
输出样例#2: 复制
0
4
4
输入样例#3: 复制
2
5 8
6 4
输出样例#3: 复制
8
6

说明

In test cases worth 50% of total points, Mirko will see only one piece of land. The dimensions of this piece of land will be smaller than 500.

Clarification​ ​of​ ​the​ ​first​ ​test​ ​case:

The first piece of land can be mowed without making any turns if he starts from the field in the first column of the table, faced to the right and only going forwards. A similar idea applies for the second piece of land.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<iomanip>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;

int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;++i)
	{
		int a,b;
		cin>>a>>b;
		if(a==1||b==1)
		{
			cout<<0<<endl;
			continue;	
		}
		else
		{
			int js=1;
			int total=0;
			if(a>b)
			{
				while(a!=0&&b!=0)
				{
					if(js%2==0) a--;
					else b--;
					total++;
					js++;
				}
			}
			else
			{
				while(a!=0&&b!=0)
				{
					if(js%2==0) b--;
					else a--;
					total++;
					js++;
				}
			}
			cout<<total-1<<endl;
		}
	}
	return 0;
}

因为没有障碍并且求最少转弯次数所以一次走完一整行或一整列就是最优解法。。。所以可以模拟为给行数或列数减一。。。

然后分析一下,画个图看一下发现当行数大于列数时先走一整行(即先给行数减一再给列数减一直至有一数为零)当行数小与列数时先走一整列(即先给列数减一再给行数减一直至有一数为零)。但上面这个代码会TLE!!

当我尝试着改成如下代码时,还是TLE!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<iomanip>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;

int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;++i)
	{
		int a,b;
		cin>>a>>b;
		if(a==1||b==1)
		{
			cout<<0<<endl;
			continue;	
		}
		else
		{
			int total=0;
			if(a>b)
			{
				while(a!=0&&b!=0)
				{
					a--;
					if(a==0)
					{
						total+=1;
						break;
					}
					b--;
					if(b==0)
					{
						total-=1;
					}
					total+=2;
				}
			}
			else
			{
				while(a!=0&&b!=0)
				{
					b--;
					if(b==0)
					{
						total+=1;
						break;
					}
					a--;
					if(a==0)
					{
						total-=1;
					}
					total+=2;
				}
			}
			cout<<total-1<<endl;
		}
	}
	return 0;
}

两个的耗时好像没啥区别。。。(真是太失败了,然后我去翻了一下题解。***竟然这么简单,竟然有公式!!!)

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<iomanip>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;

int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;++i)
	{
		int a,b;
		cin>>a>>b;
		cout<<2*min(a,b)-2<<endl;//公式
	}
	return 0;
}

转载于:https://www.cnblogs.com/poi-bolg-poi/p/10752088.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值