1. 程式人生 > >F - Elevator Stopping Plan (UVALive - 2949)

F - Elevator Stopping Plan (UVALive - 2949)

ring 思路 想要 blog turn namespace math 如何 urn

- 題目大意

某個公司只有一個電梯, 現在有n 個人從1樓, 他們有各自想要到達的樓層, 然後電梯每上一樓需要4 秒, 每在一個樓層開門需要10 秒, 然後然爬樓梯的話需要20一樓。問, 如何用最短的時間讓所有人都到達各自想要到的樓層。

- 解題思路

因為人可以爬樓梯, 所以可以在某個樓層下樓之後走樓梯到達想要到的樓層, 只要在最後一個人到達之前就可以。 對於時間可以采取二分的方式搜索, 所以只要判斷某個時間能否將所有人送到指定樓層就可以了。 對於判斷我們可以用貪心去做, 盡量讓電梯停在較高的樓層,只要剩余的時間夠使得人走到自己的樓層就可以了。

- 代碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
bool vis[36];
int num[36];
int Max,sum;
int a = 0;
bool find(int t)
{
	int i, j;
	sum = 0;
	memset(num, 0, sizeof(num));
	i = t / 20 + 2;
	while (i <=Max)
	{
		while (i < Max && !vis[i])
			i++;
		if (10 * sum + 4 * (i - 1) > t)
			return false;
		j = (t - 10 * sum + 20 * i + 4)/24;
		i = (t - 10 * sum + 16 * j + 4) / 20+1;
		num[sum++] = j;
	}
	return true;
}

int main()
{
	int n, f;
	while (cin >> n)
	{
		if (n == 0)
			break;
		Max = 0;
		memset(vis, false, sizeof(vis));
			while(n--)
			{
				cin >> f;
				vis[f] = true;
				Max = max(Max, f);
			}
			int l = 0, r = 14 * (Max - 1);
			int m;
			while (l < r)
			{
				m = (l + r + 1) / 2;
				if (m == r)
					break;
				if (find(m))
					r = m ;
				else
				{
					l = m ;
				}
			}
			find(m);
			cout << m << endl;
			cout << sum;
			for (int i = 0; i < sum; i++)
			{
				cout <<" "<<num[i];
			}
			cout << endl;
	}
	return 0;
}

  

F - Elevator Stopping Plan (UVALive - 2949)