1. 程式人生 > >UVa 1346 Songs (貪心好題)

UVa 1346 Songs (貪心好題)

思路:直接看這個和式,記A(i)=f(i)Σl(j) (1<=j<=i),則sum=ΣA(i)(別被下標迷惑了,s(i)完全可以用i代替)。

設sum已經達到最小,

記sum1 = A(i)+A(i+1) = (f(i)+f(i+1))*(l(1)+...+l(i-1)) + f(i)*l(i) f(i+1)*l(i) + f(i+1)*l(i+1)

交換f(i)和f(i+1),交換l(i)和l(i+1),得sum2= (f(i)+f(i+1))*(l(1)+...+l(i-1)) + f(i)*l(i) f(i)*l(i+1) + f(i+1)*l(i+1)

因為sum最小,必有sum1<=sum2,故f(i+1)*l(i)<=f(i)*l(i+1)

(也可以這麼理解,頻率越大的,長度越短的,即f(i)/l(i)越大的,位置越靠前)

完整程式碼:

/*0.032s*/

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

struct node
{
	int id;
	double l, f;
	bool operator < (const node& a) const
	{
		return a.f * l < f * a.l;
	}
} a[65540];

int main()
{
	int n, i, s;
	while (~scanf("%d", &n))
	{
		for (i = 1; i <= n; ++i)
			scanf("%d%lf%lf", &a[i].id, &a[i].l, &a[i].f);
		scanf("%d", &s);
		nth_element(a + 1, a + s, a + n + 1);
		printf("%d\n", a[s].id);
	}
	return 0;
}