题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=4442
题意:一个人去做运动,给定每项运动的初始等待时间和增长等待时间,一等完该运动的等待时间就相当于完成该项运动,即不考虑做运动的时间,求完成所有运动最短要多少时间。
题解:贪心,考虑两种运动,初始等待时间为a1,a2,增长等待时间为b1,b2,只会发生两种情况,先做第一个运动和先做第二个,先做第一个时间就为a1+a2+a1*b2(也可以写成a1+a2+a1*a2*(b2/a2)),同理另一种情况为a1+a2+a2*b1(a1+a2+a1*a2*(b1/a1)),所以可以发现,要使总时间最小,即是要考虑bi/ai最小,反过来ai/bi最大,大的放到后面等待即可,小的放到前面先执行,同理可得及时初始时间变化了t*bi也一样,这定理成立,所以只要考虑最初的ai/bi
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#define N 100005
using namespace std;
typedef struct
{
int a,b;
double d;
}Subject;
Subject s[N];
bool compare(Subject q,Subject w)
{
return q.d<w.d;
}
const long long mod=365*24*60*60;
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
for(int i=1;i<=n;i++)
{
scanf("%d %d",&s[i].a,&s[i].b);
s[i].d=(1.0*s[i].a)/(1.0*s[i].b);
}
sort(s+1,s+1+n,compare);
long long sum=0;
for(int i=1;i<=n;i++)
{
sum=(sum+s[i].a+sum*s[i].b)%mod;
}
printf("%lld\n",sum);
}
return 0;
}
题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=3183
题意:给定一个数字,要求去掉其中的n个数,要求去掉后的数字最小
题解:贪心,可以发现只要考虑数字从前往后递减的情况,只要递减,就去掉前面大的数,当递增时先不用考虑,到最后得到递增数字只要从后往前继续去数字就能保证最小
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#define N 1050
using namespace std;
char number[N];
char existence[N];
int main()
{
int num;
while(scanf("%s %d",number+1,&num)!=EOF)
{
int tail=2;
int len=strlen(number+1);
char last=number[1];
existence[0]=last;
int di=1;
int count1=0;
while(count1!=num&&tail<=len)
{
if(di>0&&last>number[tail])
{
di--;
if(di!=0) last=existence[di-1];
count1++;
}
else
{
existence[di++]=number[tail++];last=number[tail-1];
}
}
if(tail>len&&count1!=num) {di=di-(num-count1);}
else
{
for(int i=tail;i<=len;i++) existence[di++]=number[i];
}
int start=0;
while(existence[start]=='0'&&start<di) start++;
if(start>=di) printf("0");
else
{
for(int i=start;i<di;i++)
{
printf("%c",existence[i]);
}
}
printf("\n");
}
return 0;
}