【2022牛客多校5 A题 Don‘t Starve】DP

39 篇文章 0 订阅
17 篇文章 0 订阅

题目描述

NIO purchased a new game, Don’t Starve, a sandbox game published by Klei Entertainment Inc. This game revolves around a scientist named Wilson who finds himself in a dark and gloomy world and must survive for as long as possible.

In the very beginning, NIO should help Wilson to gather some food for survival. Assume that when controlling Wilson to walk towards a location on the map, NIO should keep pressing the left button on the mouse, and when Wilson comes to the place where there is food, NIO should stop pressing the mouse, but press the space key on the keyboard to collect the food at this location. As NIO will feel tired of pressing the mouse for a long time and his finger will become very uncomfortable after a long time of pressing, the time he is willing to press the mouse after each collection is strictly decreased. Suppose there are NN locations on the 2-D plane, and at each point, there is only one unit of food. And NIO will start at the original point on the plane. You can assume that each point has an infinite number of food items, but only one can be taken at a time.

What is the maximum amount of food can NIO get for Wilson? Note that the food will be refreshed after Wilson left.

输入输出描述

在这里插入图片描述

样例输入

7
-7 21
70 64
45 -52
68 -93
-84 -16
-83 64
76 99

样例输出

4

题意:

给你n个点,每个点都有一个食物,每个点也都有一个坐标,你可以在这些点之间走,每次的距离都必须严格小于上一次的长度,问你最多能吃到多少食物。

思路:

因为数据量是2000,所以每两个点之间的距离能在4e6的时间处理出来,然后这就是2000个点,4e6条边,时间完全ok,然后设状态dp[i]表示从(0,0)点到第i个点的能吃到食物的最多的数量,然后先把所有边按边长从大到小排序,然后从前往后dp就能保证那个距离的递减性,还有一些距离是相等的,需要在dp的时候处理出来与这个距离相同的所有边,然后把里面的值先存起来避免dp的时候把原来的值换掉以后再更新,就发生重复了,相当于环,那么看一下代码吧

#include<bits/stdc++.h>
using namespace std;
const int N = 2010;
#define int long long 
#define x first
#define y second
struct node{
	int x,y,w,id;
	bool operator<(const node&t)const{
		return w > t.w;
	}
}e[N*N];
typedef pair<int,int> PII;
int dis(PII a,PII b){
	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
PII loc[N];
int f[N*N];
signed main(){
	int n,tt=0;
	while(scanf("%lld",&n)!=EOF){
		tt = 0;
		for(int i=1;i<=n;i++){
			scanf("%lld%lld",&loc[i].x,&loc[i].y);
			e[++tt] = {i,1,dis(loc[0],loc[i]),1};
			f[i] = -1e9;
		}
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				if(i != j) e[++tt] = {i,j,dis(loc[i],loc[j]),0};
		sort(e+1,e+1+tt);
		for(int i=1;i<=tt;){
			int j = i;
			queue<PII> q;
			while(j<=tt&&e[i].w == e[j].w) j++;
			for(int k=i;k<j;k++) if(e[k].id) q.push({e[k].x,1});
			else q.push({e[k].x,f[e[k].y]+1});
			while(q.size()) f[q.front().x] = max(f[q.front().x],q.front().y),q.pop();
			i=j;
		}
		int ans = 0;
		for(int i=1;i<=n;i++) ans = max(ans,f[i]);
		cout<<ans<<endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇智波一打七~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值