贪心专题


Robbers

Special Judge  Time Limit: 2000/1000MS (Java/Others)  Memory Limit: 128000/64000KB (Java/Others)
Submit  Statistic  Next Problem

Problem Description

      N robbers have robbed the bank. As the result of their crime they chanced to get M golden coins. Before the robbery the band has made an agreement that after the robbery i-th gangster would get Xi/Y of all money gained. However, it turned out that M may be not divisible by Y.

The problem which now should be solved by robbers is what to do with the coins. They would like to share them fairly. Let us suppose that i-th robber would get Ki coins. In this case unfairness of this fact is |Xi/Y - Ki/M|. The total unfairness is the sum of all particular unfairnesses. Your task as the leader of the gang is to spread money among robbers in such a way that the total unfairness is minimized.

Input

      The first line of the input file contains numbers N, M and Y (1 ≤ N ≤ 1000, 1 ≤ M, Y ≤ 10000). N integer numbers follow - X i (1 ≤ X i ≤ 10000, sum of all X i is Y).

Output

      Output N integer numbers - K i (sum of all K i must be M), so that the total unfairness is minimal.

Sample Input

3 10 4
1 1 2

Sample Output

2 3 5


AC code:

#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
 
using namespace std;
 
#define INF 1000000000
 
int x[1010];
int k[1010];
bool flag[1010];
 
int main(){
    int n,m,y;
    while(cin>>n>>m>>y){
        memset(flag,0,sizeof(flag));
        for(int i=1;i<=n;i++){
            scanf("%d",&x[i]);
        }
         
        int mm=0;
        for(int i=1;i<=n;i++){
            k[i]=m*x[i]/y;
            if(m*x[i]%y==0){
                flag[i]=1;
            }
            mm+=k[i];
        }
        int t=m-mm;
         
        while(t--){
            double tmp=0.0;
            int j;
            for(int i=1;i<=n;i++){
                if(flag[i])continue;
                double d=( (x[i]+0.0)/y - (k[i]+0.0)/m );
                if(d>tmp){
                    tmp=d;
                    j=i;
                }
            }
            k[j]++;
        }
        for(int i=1;i<=n;i++){
            printf("%d",k[i]);
            if(i!=n)printf(" ");
        }
        printf("\n");
    }
    return 0;
}



雷霆战机

Time Limit:  2000/1000MS (Java/Others)     Memory Limit:  65536/32768KB (Java/Others)

Problem Description

风风最近迷上了一个打飞机游戏——《雷霆战机》,战机分为白二星、绿三星、蓝四星、紫五星,四种品质。当然,最厉害的是紫色五星的战机啦。

贪心专题_第1张图片
战机分为升级和进阶两种。
升级:提升战机的等级,但战机品质不变。
进阶:可将战机提升一个星级(白二星->绿三星->蓝四星->紫五星)。

为了简化问题,规定战机进阶规则如下:
白色二星:
起始等级Lv1级,满级Lv25级。
Lv1升级到Lv25,总共需要A经验。
进阶到绿色三星条件:满级Lv25后,方可进阶。
绿色三星:
起始等级Lv25级,满级Lv30级。
Lv25升级到Lv30,总共需要B经验。
进阶到蓝色四星条件:满级Lv30后,方可进阶。
蓝色四星:
起始等级Lv30级,满级Lv60级。
Lv30升级到Lv60,总共需要C经验。
进阶到紫色五星条件:满级Lv60后,方可进阶。
紫色五星:
起始等级Lv60级,满级Lv75级。
Lv60升级到Lv75,总共需要D经验。
满级LV75后,最强战机诞生!

现在风风手上有1架Lv1级的白二星,和N个经验球(可以升级战机的球球~~~),每个经验球都有一定的经验值。
每次风风都只能使用一个经验球给战机升级,并且每个经验球只能用一次后就会消失。
另外,风风有个习惯。就是每次都会优先选择能将战机升级到相应星级对应的满等级的最小的经验球。若剩下的经验球中最大的经验球也不能将现在的战机升到满级,那么风风就会选择这些剩下的经验球里面经验值最大的那个经验球对战机进行升级了。
如果按照风风的方式对战机进行升级进阶,风风能否成功将自己的战机升级到满级LV75的紫色战机呢?
如果能,请告诉风风,他最后剩下的未被使用的经验球的经验总和是多少?

注意:如果使用某个经验球使战机升级到满级了,那么多出的经验是不会累积的,这时候你需要对战机进阶到下一个品质,提升满级的等级。才可以继续升级。
例如:
现在有一架绿色三星Lv29的战机,还需要80的经验可以升级到满级Lv30。如果你使用了经验为9999的经验球。只能将战机升级到满级Lv30,而不会升级到Lv31级以上,经验值不会累积。因为在使用经验球的同时,无法进行进阶。因为进阶需要满级后,才可以进阶。
另外,值得一提的是:如果是一架绿色三星Lv9的战机,还需要10的经验升级到Lv10,而Lv10到Lv11需要15点经验,Lv11到Lv12需要22点经验。那么你使用经验值为30的经验球,可以将战机直接升级到Lv11,并且还需要17点经验升级到Lv12。(也就是说还未达到满级的战机,使用经验球可以跨级升级,而满级后,需要进阶到下一个品质,才可以继续升级)。

Input

输入包含多组数据,对于每组数据:
第一行:N(表示有N个经验球,1<=N<=1000)
第二行:A B C D(分别表示各个星级从起始级升到相应星级的满级所需的总经验,详情见上述题目描述,1<=A,B,C,D<=99999)
第三行:N个经验球的经验值EXP[i] (1<=EXP[i]<=99999)

Output

如果能进阶到满级Lv75紫色战机,输出“YES”,并输出最后剩下的未被使用的经验球的经验总和是多少。
如果不能,输出“NO”。

Sample Input

3
400 250 800 2000
99999 99999 99999
4
400 2000 5000 10000
9999 9999 9999 9999
4
400 2000 5000 10000
99999 99999 99999 99999
5
1000 2000 8000 10000
1000 2000 5000 10000 20000 

Sample Output

NO
NO
YES 0
YES 5000


AC code:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#define LL long long
#define MAXN 1000010
using namespace std;
LL a[5];
LL n,m,t,cnt,sum,k,f,ff,mm;
LL x[1111],fg[1111];
int main()
{
	int i,j;
	//freopen("D:in.txt","r",stdin);
	while(cin>>n)
	{
		mm=0;
		ff=1;
		for(i=1;i<=4;i++)
		{
			cin>>a[i];
			mm=max(mm,a[i]);
		}
		sum=0;
		for(i=1;i<=n;i++)
		{
			cin>>x[i];
			sum+=x[i];
			if(x[i]>=mm)
				ff=0;
		}
		if(n<4)
		{
			printf("NO\n");
		}
		else
		{
			sort(x+1,x+n+1);
			cnt=0;
			memset(fg,0,sizeof(fg));
			for(i=1;i<=4;i++)
			{
				for(j=1;j<=n;j++)
				{
					if(x[j]>=a[i]&&!fg[j])
					{
						fg[j]=1;
						sum-=x[j];
						cnt++;
						break;
					}
				}
				if(j==n+1)
				{
					for(j=n;j>=1;j--)
					{
						if(!fg[j])
						{
							sum-=x[j];
							fg[j]=1;
							a[i]-=x[j];
							i--;
							break;
						}
					}
				}
				
			}
			if(cnt<4)
			{
				printf("NO\n");
			}
			else
			{
				cout<<"YES "<<sum<<endl;
			}
		}
	}
	return 0;
}



ACdream王国的士兵

Time Limit:  2000/1000MS (Java/Others)     Memory Limit:  128000/64000KB (Java/Others)

Problem Description

所谓弱国无外交,ACdream王国想守住这一片土地,自然离不开王国的士兵们,你作为王国的骠骑大将军,自然有训练王国士兵的职责。王国有n个士兵,每个士兵都有两个属性,攻击和防御。然后你希望经过一系列的调整,每个士兵都能成为合格的军人,所谓合格的军人,是指他的攻击和防御之和大于等于k。你的调整办法就是交换两个士兵的同一种属性,即把两个士兵的攻击交换,或者防御交换,或者攻击和防御都交换(虽然这个没有意义)。你的调整次数没有限制。请问你能否让所有的士兵都成为合格的军人?

Input

多组数据,每组数据首先是两个整数n(1<=n<=1000),k(1<=k<=10^9)

接下来是一行整数,共n个,表示n个士兵的攻击值

接下来又是一行整数,共n个,表示n个士兵的防御值。

Output

对于每组数据,若可以通过有限次交换,使得所有的士兵都是合格的军人,就输出“YES”,否则输出“NO”(不需要双引号,注意大小写)

Sample Input

3 10
2 1 3
7 8 9
4 5
1 2 2 1
3 3 3 4

Sample Output

YES
NO

Hint

对于样例一,只需要把第一个士兵的攻击与第三个士兵的攻击交换,第二个士兵的攻击再与第三个士兵的攻击交换,即可让三个士兵的攻击+防御都为10,都是合格的军人。

对于样例二,无论如何交换,均无法让四个士兵都成为合格的军人。


AC  code:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#define LL long long
#define MAXN 1000010
using namespace std;
LL a[1111],b[1111];
LL n,m,t,cnt,sum,k;
LL s;
int main()
{
	int fg,i;
	while(cin>>n>>k)
	{
		s=0;
		sum=0;
		for(i=1;i<=n;i++)
		{
			cin>>a[i];
			sum+=a[i];
		}
		for(i=1;i<=n;i++)
		{
			cin>>b[i];
			sum+=b[i];
		}
		if(sum<n*k)
		{
			printf("NO\n");
		}
		else
		{
			sort(a+1,a+n+1);
			sort(b+1,b+n+1);
			fg=1;
			for(i=1;i<=n;i++)
			{
				if(a[i]+b[n-i+1]<k)
				{
					fg=0;
					break;
				}
			}
			if(fg)
			{
				printf("YES\n");
			}
			else
			{
				printf("NO\n");
			}
		}
	}
	return 0;
}




New Year Bonus Grant

Time Limit:  2000/1000MS (Java/Others)     Memory Limit:  128000/64000KB (Java/Others)      Special Judge

Problem Description

      All programmers of Mocrosoft software company are organized in a strict subordination hierarchy. Every programmer has exactly one chief, except Bill Hates who is also the head of the company and has no chief.
      Due to the celebration of the new 2003 year, chief accountant of Mocrosoft decided to pay a New Year Bonus Grant of 1000 dollars to some programmers. However being extremely concerned of the company wealth she would like to designate the least possible amount of money for these grants. On the other hand she didn’t want to be accused of being too greedy or of giving preferences to some programmers. To do this, she developed the following scheme of grants appointment:
• Each programmer may either assign a grant to one of his subordinates or have a grant assigned to him by his chief or none of the above.
• No programmer can simultaneously receive a grant and assign a grant to one of his subordinates.
• No programmer can assign a grant to more than one of his subordinates
      The scheme seemed to be designed perfectly — nobody would like to assign a grant to anybody since in this case he himself would not receive money. But programmers somehow discovered the plan of chief accountant and decided to make a trick to get the most money possible and share them fairly afterwards. The idea was to make such grant assignments that the total amount of grant money received is maximum possible.
      You were selected to write the program which will find the optimal grants appointment.

Input

      The first line of the input file contains integer N — the number of programmers in Mocrosoft company (2 ≤ N ≤ 500 000). Each programmer is assigned his unique identifier — integer number ranging from 1 to N . Bill Hates has number 1 and each programmer has the number greater then the number of his chief. The second line of the input file contains N − 1 integers, i-th of which being the number of the chief of the worker whose number is (i + 1).

Output

      On the first line of the output file print the maximum possible amount of money workers can get. On the second line output the numbers of programmers that will receive grant in ascending order.

Sample Input

4
1 1 2

Sample Output

2000
3 4
AC  code(暂没AC):




ACdream王国的花店

Time Limit:  2000/1000MS (Java/Others)     Memory Limit:  128000/64000KB (Java/Others)

Problem Description

ACdream王国的花店只有一家,所以大家想买花来装饰,店主为了防止有人恶意囤积鲜花来抬高物价(就是黄牛党啦~),于是就定下一个规矩:你买得越多,下一次买的单价就越贵!假设一个人已经购买了x朵鲜花,那么下一次购买第i朵鲜花的单价就是(x+1)*c[i],其中c[i]是一个店主为每一朵花的基本定价。

ACdream学校想开运动会,需要n朵鲜花来装饰,于是你和你的小伙伴总共m个人就得想办法花最少的钱去完成任务。请问机智的你最少需要花费多少钱呢?

Input

多组数据,每组数据首先是两个正整数,n(1<=n<=100),m(1<=m<=100)

然后是m个整数c[i],(1<=c[i]<=10^6)

Output

对于每组数据,输出一个整数,表示你需要花费的最少价格。

Sample Input

3 3
2 5 6
3 2
2 5 6

Sample Output

13
15
AC code:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#define LL long long
#define MAXN 1000010
using namespace std;
LL a[111];
LL n,m,t,cnt,sum;
LL s;
int main()
{
	int i;
	while(cin>>n>>m)
	{
		s=0;
		sum=0;
		for(i=1;i<=n;i++)
		{
			cin>>a[i];
			sum+=a[i];
		}
		if(m>=n)
		{
			s=sum;
		}
		else
		{
			sort(a+1,a+n+1);
			for(i=n-m+1;i<=n;i++)
				s+=a[i];
			t=2;
			cnt=0;
				for(i=n-m;i>=1;i--)
				{
					s+=a[i]*t;
					cnt++;
					if(cnt==m)
					{
						t++;
						cnt=0;
					}
				}
				
		}
		cout<<s<<endl;
	}
	return 0;
}


ACdream发电站

Time Limit:  2000/1000MS (Java/Others)     Memory Limit:  128000/64000KB (Java/Others)

Problem Description

在ACdream王国中,有一条母亲河,这条母亲河为王国人民提供了各种生活用水。在河边共住着n户人家,每户人家的位置为x[i]。由于经济发展需要,ACdream决定在这条母亲河上建立一个水力发电站,经过勘测,这个水力发电站只可以建立在区间[a,b]的某一个地方x0。为了减少大家受到来此发电站的影响,希望min{|x[i]-x0| |0<=i<=n-1}最大,即使得距离发电站最近的人家与发电站的距离最大。若有多组答案,输出坐标较小的即可。

Input

多组数据,对于每组数据,首先是三个整数n(1<=n<=100),a,b(1<=a<=b<=10^9)

接下来是n个整数,表示每户人家的坐标

 

Output

对于每组数据,输出一个整数,表示最佳发电站的坐标位置。

Sample Input

3 4 9
5 8 14

Sample Output

4

AC  code(暂没AC):



ACdream的高速公路

Time Limit:  2000/1000MS (Java/Others)     Memory Limit:  128000/64000KB (Java/Others)      Special Judge

Problem Description

ACdream王国有一条贯穿整个王国的高速公路,一天,你要驾驶着一辆油箱容量为P的车从高速公路的一头驶向另一头,总路程为L千米,每单位体积的汽油可维持行驶W千米,显然路途遥远~总有不够油的情况,所以就要加油~!

再高速公路上总共有N个加油站,但是由于是不同人开的,因此定价也参差不齐。

现在你知道每个加油站的位置,以及每个加油站的单价,问你最少需要多少钱才能到达另一头?

Input

多组数据,每组数据首先是四个整数,P(1<=P<=100),L(1<=L<=30000),W(1<=W<=20),N(1<=N<=500),分别代表油箱容量,路程,每单位体积的路程,加油站数目。

接下来是N行,每行包括一个精确到百分位的实数X(9<X<=10)以及一个整数Y(0<=Y<=L),分别表示每个加油站的单价以及每个加油站的位置。

Output

对于每组数据,如果能顺利抵达终点,则先输出一个"YES",然后输出最少花费。

否则输出一个"NO",再输出最远可以到达的位置。

字符串不包括双引号,注意大小写,输出数字只需要精确到百分之一即为正确。

Sample Input

50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300
50 1300 12 2
7.10 0
7.00 600

Sample Output

YES
749.17
NO
1200.00
AC code:

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define ll long long
struct station
{
    int loc;
    double p;
}a[600];

bool cmp(station a,station b)
{
    return a.p<b.p;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int v,s,w,n;
    double price[32010],cnt;
    while(cin>>v)
    {
        cin>>s>>w>>n;
        cnt=0.0;
        for(int i=0;i<n;i++)
            cin>>a[i].p>>a[i].loc;
        sort(a,a+n,cmp);
        for(int i=1;i<=s;i++)
            price[i]=INT_MAX/10;
        for(int i=0;i<n;i++)
            for(int j=1;j<=v*w;j++)
                if(price[a[i].loc+j]>a[i].p)
                    price[a[i].loc+j]=a[i].p;
        int k;
        for(k=1;k<=s;k++)
            if(price[k]==INT_MAX/10)
                break;
            else
                cnt+=price[k];
        if(k<=s)
            printf("NO\n%d\n",k-1);
        else
            printf("YES\n%.2f\n",cnt/w);
    }
    return 0;
}


你可能感兴趣的:(算法,ACM)