Treasure Hunting Codeforces Round #577 (Div. 2)

该博客详细介绍了Codeforces Round #577 (Div. 2)中的一道题目,题目要求在限制移动方向(不能向下,只能在特定列向上)的情况下,从起始位置(1,1)收集所有宝藏的最小步数。博主提供了题意解析、数据规模问题以及一种利用预处理和动态规划的解决方案。" 108732511,9190212,启动与登录MySQL服务器指南,"['MySQL', '数据库管理', '服务器启动', '登录方法']
摘要由CSDN通过智能技术生成

链接: https://codeforces.com/contest/1201/problem/D
题面:
You are on the island which can be represented as a n×m table. The rows are numbered from 1 to n and the columns are numbered from 1 to m. There are k treasures on the island, the i-th of them is located at the position (ri,ci).

Initially you stand at the lower left corner of the island, at the position (1,1). If at any moment you are at the cell with a treasure, you can pick it up without any extra time. In one move you can move up (from (r,c) to (r+1,c)), left (from (r,c) to (r,c−1)), or right (from position (r,c) to (r,c+1)). Because of the traps, you can’t move down.

However, moving up is also risky. You can move up only if you are in a safe column. There are q safe columns: b1,b2,…,bq. You want to collect all the treasures as fast as possible. Count the minimum number of moves required to collect all the treasures.

Input
The first line contains integers n, m, k and q (2≤n,m,k,q≤2e5, q≤m) — the number of rows, the number of columns, the number of treasures in the island and the number of safe columns.

Each of the next k lines contains two integers ri,ci, (1≤ri≤n, 1≤ci≤m) — the coordinates of the cell with a treasure. All treasures are located in distinct cells.

The last line contains q distinct integers b1,b2,…,bq (1≤bi≤m) — the indices of safe columns.

Output
Print the minimum number of moves required to collect all the treasures.
题意: 给你一个矩形,起始点在(1,1),在一些格子里有宝物,你需要将整个图中的宝物全部收集起来,而且你不能向下走,而且只有在所给出的列上你才能向上走,问最少要走多少格
思路: 由于数据过大,不可能将整个图开出来
所以我们可以预处理每一行的所在宝物的最左边与最右边,然后进行由下往上dp,上行的点由下行的所在宝物的最左边与最右边出发得到

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll n,m,k,q,x,y,a[N][2],dp[N][2],b[N];
ll sl(int j,int u,int i,int v)
{
	ll sum=INF,sum1=INF;
	ll p=lower_bound(b+1,b+1+q,a[j][u])-b;
	if(p<=q)
		sum=abs(a[j][u]-b[p])+abs(a[i][v]-a[i][v^1])+abs(b[p]-a[i][v^1]);
	p=upper_bound(b+1,b+1+q,a[j][u])-b-1;
	if(p)
		sum1=abs(a[j][u]-b[p])+abs(a[i][v]-a[i][v^1])+abs(b[p]-a[i][v^1]);
	return min(sum1,sum);
}
int main()
{
	scanf("%lld%lld%lld%lld",&n,&m,&k,&q);
	for(int i=1;i<=n;i++)
	{
		a[i][0]=INF;
		a[i][1]=-INF;
		dp[i][0]=dp[i][1]=(1ll<<60);
	}
	for(int i=1;i<=k;i++)
	{
		scanf("%d%d",&x,&y);
		a[x][0]=min(y,a[x][0]);
		a[x][1]=max(y,a[x][1]);
	}
	a[1][0]=1,a[1][1]=max(a[1][1],1ll);
	for(int i=1;i<=q;i++)
		scanf("%lld",&b[i]);
	sort(b+1,b+1+q);
	int j=1;
	dp[1][0]=abs(a[1][1]-1)+abs(a[1][1]-a[1][0]),dp[1][1]=abs(a[1][1]-1);
	for(int i=2;i<=n;i++)
	{
		if(a[i][0]==INF)
			continue;
		for(int v=0;v<2;v++)
		{
			for(int u=0;u<2;u++)
			{
				dp[i][v]=min(dp[i][v],dp[j][u]+sl(j,u,i,v)+i-j);
			}
		}
		j=i;
	}
	printf("%lld\n",min(dp[j][0],dp[j][1]));
	return 0;
}
好的,这道题目比较有趣,我可以帮你分步骤实现。首先我们需要定义地图的大小和宝藏的位置,可以先让用户输入行数和列数,再生成随机的宝藏位置。 ```c++ #include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main() { srand(time(NULL)); // 初始化随机数生成器 int row, col; // 地图的行数和列数 cout << "请输入地图的行数和列数:"; cin >> row >> col; char map[row][col]; // 定义地图数组 int treasure_row = rand() % row; // 随机生成宝藏的行数 int treasure_col = rand() % col; // 随机生成宝藏的列数 int player_row, player_col; // 初始化玩家的位置 do { player_row = rand() % row; player_col = rand() % col; } while (player_row == treasure_row && player_col == treasure_col); // 玩家和宝藏不能在同一个位置 // 初始化地图 for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (i == player_row && j == player_col) { map[i][j] = 'O'; // 玩家的位置用 O 表示 } else if (i == treasure_row && j == treasure_col) { map[i][j] = 'X'; // 宝藏的位置用 X 表示 } else { map[i][j] = '.'; // 其他位置用 . 表示 } cout << map[i][j]; } cout << endl; } return 0; } ``` 接下来我们需要让玩家可以通过输入控制角色移动,直到找到宝藏。 ```c++ #include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main() { srand(time(NULL)); int row, col; cout << "请输入地图的行数和列数:"; cin >> row >> col; char map[row][col]; int treasure_row = rand() % row; int treasure_col = rand() % col; int player_row, player_col; do { player_row = rand() % row; player_col = rand() % col; } while (player_row == treasure_row && player_col == treasure_col); for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (i == player_row && j == player_col) { map[i][j] = 'O'; } else if (i == treasure_row && j == treasure_col) { map[i][j] = 'X'; } else { map[i][j] = '.'; } cout << map[i][j]; } cout << endl; } while (true) { char move; cout << "请输入移动方向(w/a/s/d):"; cin >> move; // 根据输入的方向移动玩家 switch (move) { case 'w': if (player_row > 0) { map[player_row][player_col] = '.'; player_row--; } break; case 'a': if (player_col > 0) { map[player_row][player_col] = '.'; player_col--; } break; case 's': if (player_row < row - 1) { map[player_row][player_col] = '.'; player_row++; } break; case 'd': if (player_col < col - 1) { map[player_row][player_col] = '.'; player_col++; } break; default: cout << "输入无效,请重新输入。" << endl; continue; } // 判断是否找到宝藏 if (player_row == treasure_row && player_col == treasure_col) { map[player_row][player_col] = '$'; // 找到宝藏后用 $ 替换掉 X 和 O for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { cout << map[i][j]; } cout << endl; } cout << "游戏结束,恭喜你完成游戏。" << endl; break; } else { map[player_row][player_col] = 'O'; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { cout << map[i][j]; } cout << endl; } } } return 0; } ``` 现在你可以运行程序,测试一下你的控制台地图游戏啦!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值