1. 程式人生 > 實用技巧 >CSUST 4006-你真的會樹套樹套樹嗎?(貪心|dp)

CSUST 4006-你真的會樹套樹套樹嗎?(貪心|dp)

題目連結:http://acm.csust.edu.cn/problem/4006
CSDN食用連結:https://blog.csdn.net/qq_43906000/article/details/107800144

Description

\(gay\) 黃和 \(gay\) 行在一次探險過程中,獲得了 \(n\) 顆寶石,第 \(i\) 顆寶石有 \(a[i]\) 的價值。

為了公平起見,他們決定要儘可能的使得他們 \(2\) 個人所獲得的寶石價值儘可能的接近。

但是他們有點懶,想讓學弟學妹們幫幫他們,給他們一個分配方案。

你能幫幫他們嗎?

Input
第一行輸入一個整數 \(n\)\(2\leq n\leq 1e5\)

,代表給定正整數的數量。
第二行輸入\(n\)個正整數\(a1,a2,a3\cdots (1\leq ai)\)所有a[i]的和不超過 \(2 * n - 2\)

Output
每組資料輸出一個長度為 \(n\)\(01\) 序列,\(0\) 表示 \(gay\) 黃所選,\(1\)表示 \(gay\) 行所選。答案可能不唯一,輸出任意滿足要求的 \(01\) 序列即可。

Sample Input 1
6
1 5 1 1 1 1
Sample Output 1
010000

Sample Input 2
4
2 1 2 1
Sample Output 2
0011

emmm,本來說這題是個防AK來著。。。結果被我們亂搞成了簽到題。。。

實際上我們如果能夠注意到a[i]總和不超過\(2*n-2\)的話,那麼我們就可以大膽地來一波貪心,因為,如果\(a_i\)總和小於等於\(2*n-2\)的話,那麼一定有足夠多的一來填補最大和次大的空缺,可以得出的是1的個數一定會超過\(\frac{n}{2}\),那麼大膽貪一波就是取一個最大的,取一個次大的,然後再取1來彌補中間的空缺就好了。

以下是AC程式碼:

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

const int mac=1e5+10;

struct node
{
	int id,val;
	bool operator<(const node&a)const{
		return val<a.val;
	}
}a[mac];
int vis[mac];

int main(int argc, char const *argv[])
{
	int n;
	scanf ("%d",&n);
	for (int i=1; i<=n; i++) {scanf ("%d",&a[i].val); a[i].id=i;}
	sort(a+1,a+1+n);
	int head=1,tail=n;
	while (tail>=head){
		vis[a[tail].id]=1;
		int s=a[tail-1].val;
		while (s<a[tail].val) s+=a[head++].val;
		tail-=2; 
	}
	for (int i=1; i<=n; i++)
		if (!vis[i]) printf("0");
		else printf("1");
	printf("\n");
	return 0;
}