1. 程式人生 > 其它 >P7302 [NOI1998] 免費的餡餅

P7302 [NOI1998] 免費的餡餅

題面

SERKOI 最新推出了一種叫做 “免費餡餅” 的遊戲:遊戲在一個舞臺上進行。舞臺的寬度為 \(w\) 格(從左到右依次用 \(1\sim w\) 編號),遊戲者佔一格。開始時遊戲者可以站在舞臺的任意位置,手裡拿著一個托盤。下圖為天幕的高度為 \(4\) 格時某一個時刻遊戲者接餡餅的情景。

遊戲開始後,從舞臺天幕頂端的格子中不斷出現餡餅並垂直下落。遊戲者左右移動去接餡餅。遊戲者每秒可以向左或者向右移動一格或兩格,也可以以站在原地不動。

當餡餅在某一時刻恰好到達遊戲者所在的格子中,遊戲者就收集到了這塊餡餅。當餡餅落在一個遊戲者不在的格子裡時該餡餅就消失。

寫一個程式,幫助我們的遊戲者收集餡餅,使得所收集餡餅的分數之和最大。

思路

免費的餡餅,免費的陷阱

1.貪心做法

先對原資料排序(優先時間從小到大,然後是價值從大到小)。然後跑貪心。先選第一個,然後如果時間足夠移動就移動。

複雜度是 \(O(n\log n)\)

#include <bits/stdc++.h>
using namespace std;

struct Pie{
	int t,p,v;	
} a[100005],last;
int w,n,ans;

bool cmp(Pie x,Pie y){
	if(x.t==y.t){
		return x.v>y.v;
	}
	else{
		return x.t<y.t;
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>w>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].t>>a[i].p>>a[i].v;
	}
	sort(a+1,a+n+1,cmp);
	last=a[1];
	ans=a[1].v;
	for(int i=2;i<=n;i++){
		if(2*(a[i].t-last.t)>=abs(a[i].p-last.p)){
			ans+=a[i].v;
			last=a[i];
		}
	}
	cout<<ans<<endl;
	return 0;
}

可以水 \(50\) 分。