1. 程式人生 > >演算法提高 盾神與積木遊戲

演算法提高 盾神與積木遊戲

問題描述   最近的m天盾神都去幼兒園陪小朋友們玩去了~
  每個小朋友都拿到了一些積木,他們各自需要不同數量的積木來拼一些他們想要的東西。但是有的小朋友拿得多,有的小朋友拿得少,有些小朋友需要拿到其他小朋友的積木才能完成他的大作。如果某個小朋友完成了他的作品,那麼他就會把自己的作品推倒,而無私地把他的所有積木都奉獻出來;但是,如果他還沒有完成自己的作品,他是不會把積木讓出去的喲~
  盾神看到這麼和諧的小朋友們感到非常開心,於是想幫助他們所有人都完成他們各自的作品。盾神現在在想,這個理想有沒有可能實現呢?於是把這個問題交給了他最信賴的你。 輸入格式   第一行為一個數m。
  接下來有m組資料。每一組的第一行為n,表示這天有n個小朋友。接下來的n行每行兩個數,分別表示他現在擁有的積木數和他一共需要的積木數。 輸出格式   輸出m行,如果第i天能順利完成所有作品,輸出YES,否則輸出NO。 樣例輸入 2
2
2 2
1 3
3
1 5
3 3
0 4 樣例輸出 YES
NO 資料規模和約定

  1<=n<=10000,1<=m<=10。

這個題目用貪心演算法,將每天積木夠完成作品的同學分成一組,組號為E,不夠的同學分成一組,組號為I,並將積木不夠的同學按照需要的積木-擁有的積木的差值按從小到大排序,E組中公共有sum個積木,將sum個積木依次分給I組中的同學,如果不夠輸出NO,如果夠,sum更新,並繼續往下分。

例如

5
2 2
3 2
1 5
2 10
3 9

E組

2 2

3 2

I組(已排序)

1 5

3 9

2 10

sum=2+3=5

I組中第一個小朋友 還需要4個積木而sum>4,所以夠 sum更新為6(第一個小朋友用完後他的積木也可以空出來)

第二個小朋友還需要6個積木,而sum=6,所以夠,sum更新為9

第三個下小朋友需要8個積木,而sum>8,所以夠,sum更新為11

於是所有小朋友都能完成自己的作品,輸出YES

#include<iostream>    
#include<vector>
#include<algorithm>
using namespace std;    
struct bricks//積木結構體,have表擁有的積木,need表需要的積木
{
	int have,need;
}b;
vector<bricks> I,E;//I,E 與上面含義相同
int cmp(bricks a,bricks b)//I組排序
{
	return (a.need-a.have)<(b.need-b.have);
}
int main()    
{    
	int m,n,sum=0,flag=1;//flag為是否夠得標誌,sum與上面含義相同
	cin>>m;
	for(int i=0;i<m;i++)
	{
		sum=0;//每次都置零
		flag=1;
		I.clear();
		E.clear();
		cin>>n;
		for(int j=0;j<n;j++)
		{
			cin>>b.have>>b.need;
			if(b.have>b.need)//分組,如果自己的積木夠完成作品,分到E組
			{
				E.push_back(b);
				sum+=b.have;	
			}
			else//不能完成分到I組
				I.push_back(b);
		}
		sort(I.begin(),I.end(),cmp);//排序
		for(vector<bricks>::iterator k=I.begin();k!=I.end();k++)
		{
			if(sum<((*k).need-(*k).have))//不夠的情況
			{
				flag=0;
				break;
			}
			else//夠得話更新sum
				sum+=(*k).have;
		}
		if(flag)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;	
	} 
	return 0;   
}