C++题解:糖果

     目录

题目 

题解


题目 

  •  3000ms
  •  524288K

DD 生活在一个城镇里,这个城镇上有 n 个糖果铺,其中第 i 个坐标是 (xi​,yi​),因为她很可爱,所以每当她经过一个糖果铺的时候店主就会送给她一个糖果,需要注意的是如果她多次经过同一个店铺是可以收获多颗糖的。她初始的时候站在原点上,每次可以选择前往一个除自己以外的店铺,但是 DD 很懒,她希望每次行走的距离的严格小于上一次行走的距离,她现在想知道自己最多可以收获多少个糖果

输入格式

第一行一个整数表示 n

接下来 n 行每行两个整数表示 x_i,y_i

输出格式

输出 DD 最多可以收获多少个糖果

输出时每行末尾的多余空格,不影响答案正确性

要求使用「文件输入输出」的方式解题,输入文件为 candy.in,输出文件为 candy.out

样例输入

5
5 8
4 10
3 1
3 2
3 3

样例输出

6

题解:

知识点:动态规划

分析:

题目要求下一条路的长度严格小于这一条路,那么我们可以从短的路到长的路来反着进行更新,这样可以保证距离长的边不会对距离短的边产生更新。

设dpi,j​表示上一个点为i ,这一个点为j 时从j 出发继续走可以获得的最大收益;设fi 表示从点i ii出发继续走可以获得的最大收益,这里由于我们是从短到长进行更新的,所以f 表示的其实是走过的边小于当前边时的最大收益,当更新完时,f就是全局的最大收益。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 2005;
int n;
int x[maxn];
int y[maxn];
int dp[maxn][maxn];	// dp[i][j]表示从i到j这一条边i可以收获的最大值
int f[maxn];		// f[i]表示从i点出发的可以收获的最大值
struct Edge{
	int u;//节点
	int v;//节点
	long long w;//价值
	Edge() {};//一定要有
	Edge(int a, int b){
		u = a;
		v = b;
		w = pow(x[a] - x[b], 2) + pow(y[a] - y[b], 2);//欧几里得距离的平方
	}
}e[maxn * maxn + maxn];
bool cmp(const Edge &x, const Edge &y){
	return x.w < y.w;
}
int total = 0;//记第几个
int main(){
	freopen("candy.in","r",stdin);
    freopen("candy.out","w",stdout);
    scanf("%d", &n);
	for (int i = 1; i <= n; i++){
		scanf("%d%d", x + i, y + i);
	}
	for (int i = 1; i <= n; i++){//加边
		e[total++] = Edge(0, i);
	}
	for (int i = 1; i <= n; i++){//加边
		for (int j = i + 1; j <= n; j++){
			e[total++] = Edge(i, j);
			e[total++] = Edge(j, i);
		}
	}
	sort(e, e + total, cmp);//排序
	for (int i = 0; i < total; i++){
		int j = i + 1;
		while (e[j].w == e[i].w){//由于题目中要求路径严格递减,所以长度相同的边必须特殊考虑,即同时更新。先更新边,再更新点。
			j++;
		}
		for (int k = i; k < j; k++){
			int &dis = dp[e[k].u][e[k].v];
			dis = max(dis, f[e[k].v] + 1);
		}
		for (int k = i; k < j; k++){
			Edge &tmp = e[k];
			f[tmp.u] = max(f[tmp.u], dp[tmp.u][tmp.v]);
		}
		i = j - 1;
	}
	printf("%d\n", f[0]);
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!对于扫雷游戏的题解,我可以给你一些思路和代码示例。首先,你需要了解扫雷游戏的规则和要求。接下来,你可以使用C++语言来实现游戏逻辑和界面。 下面是一个简单的扫雷游戏的C++代码示例: ```cpp #include <iostream> #include <vector> #include <random> using namespace std; class MinesweeperGame { private: int rows; int cols; vector<vector<char>> board; vector<vector<bool>> revealed; vector<pair<int, int>> directions = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}; public: MinesweeperGame(int m, int n, int mineCount) { rows = m; cols = n; board.resize(rows, vector<char>(cols, ' ')); revealed.resize(rows, vector<bool>(cols, false)); placeMines(mineCount); calculateNumbers(); } void printBoard() { cout << " "; for (int j = 0; j < cols; j++) { cout << j << " "; } cout << endl; for (int i = 0; i < rows; i++) { cout << i << " |"; for (int j = 0; j < cols; j++) { cout << board[i][j] << "|"; } cout << endl; } } bool isGameOver() { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (board[i][j] == 'M' && revealed[i][j]) { return true; } } } return false; } void reveal(int row, int col) { if (row < 0 || row >= rows || col < 0 || col >= cols || revealed[row][col]) { return; } revealed[row][col] = true; if (board[row][col] == 'M') { return; } if (board[row][col] == '0') { for (auto dir : directions) { reveal(row + dir.first, col + dir.second); } } } private: void placeMines(int mineCount) { random_device rd; mt1

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值