ZOJ 1029
资源占用问题
求出最大的重叠次数*10是答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,s[201],a,b,i;
memset(s,0,sizeof(s));
cin>>n;
while(n--)
{
cin>>a>>b;
if(a>b)a^=b^=a^=b;
a++;b++;//注意走廊位置与房间号的关系即可
for(i=a/2;i<=b/2;i++)s[i]++;
}
int ma=0;
for(i=0;i<201;i++)if(ma<s[i])ma=s[i];
printf("%d\n",ma*10);
}
return 0;
}
UVA 1344 Tian Ji -- The Horse Racing
题意:田忌和齐王各有n匹马。已知所有马的速度。。赢一场赚200,输一场输200,平局没输赢。要求出田忌最好的情况。。。其实就是田忌赛马啦。。
思路:贪心。。先把2人的马存成数组。从小到大排序。。
然后情况比较多。。这样考虑:
如果田忌最好的马比齐王最好的马快,就比赛。赚200.。
如果田忌最好的马比齐王最好的马慢,就拿田忌最垃圾的马和齐王这匹马比赛。亏200.。
如果田忌最好的马比齐王最好的马速度相同,就比较田忌和齐王最垃圾的马
如果田忌最垃圾的马比齐王最垃圾的马快,就比赛。赚200.。
如果田忌最垃圾的马比齐王最垃圾的马慢,就拿田忌的这匹马和齐王最好的马比赛。亏200.。
如果田忌最垃圾的马比齐王最垃圾的马速度相同,就比较田忌这匹马和齐王最好的马。
田忌最垃圾的马速度只可能小于等于齐王最好的马
如果田忌最垃圾的马和齐王最好的马相同。那么说明他们剩下马的速度都相同。。后面全是平局,直接结束判断
如果田忌最垃圾的马比齐王最好的马慢,就比赛,亏200.
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
int n,a[1001],b[1001];
while(~scanf("%d",&n))
{
int i,j,k=0,m=0;
int ans=0;
for(i=0;i<n;i++)scanf("%d",&a[i]);
for(i=0;i<n;i++)scanf("%d",&b[i]);
sort(a,a+n);
sort(b,b+n);
for(i=n-1,j=n-1;i>=k;)
{
if(a[i]>b[j]){
i--;
j--;
ans+=200;
}
else if(a[i]<b[j])
{
j--;
k++;
ans-=200;
}
else{
if(a[k]>b[m])
{
k++;
m++;
ans+=200;
}
else if(a[k]<b[m])
{
k++;
j--;
ans-=200;
}
else{
if(a[k]==b[j])break;
else
{
k++;
j--;
ans-=200;
}
}
}
}
printf("%d\n",ans);
}
return 0;
}
ZOJ1076 很简单的贪心
贪心,先按任务的结束时间递减排序,再逐个选择。选择活动的起始时间大于已选择活动的结束时间
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
struct ss
{
int x1,x2;
int ord;
}a[1010];
bool cmp(ss a,ss b)
{
if(a.x2!=b.x2)return a.x2<b.x2;
return a.x1<b.x1;
}
int main()
{
int n,i;
vector<int>s;
while(~scanf("%d",&n)&&n)
{
s.clear();
for(i=0;i<n;i++){
scanf("%d%d",&a[i].x1,&a[i].x2);
a[i].ord=i+1;
}
sort(a,a+n,cmp);
s.push_back(a[0].ord);
// for(i=0;i<n;i++)printf("%d %d %d\n",a[i].x1,a[i].x2,a[i].ord);
int en=a[0].x2;
for(i=1;i<n;i++)
{
if(a[i].x1>=en){
s.push_back(a[i].ord);
en=a[i].x2;
}
}
for(i=0;i<s.size();i++)
{
if(i)printf(" %d",s[i]);
else printf("%d",s[i]);
}
printf("\n");
}
return 0;
}
ZOJ3721 贪心 题意是尽可能每天多安排考试
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<iostream>
#include<algorithm>
struct ss
{
int s,t;
int day,pos;
}a[100010];
bool cmp(ss a,ss b)
{
if(a.s==b.s)return a.t<b.t;
return a.s<b.s;
}
bool cmp1(ss a,ss b)
{
if(a.day==b.day)return a.pos<b.pos;
return a.day<b.day;
}
using namespace std;
int main()
{
int n,i;
while(~scanf("%d",&n))
{
for(i=0;i<n;i++){
scanf("%d%d",&a[i].s,&a[i].t);
a[i].pos=i+1;
}
sort(a,a+n,cmp);
a[0].day=1;
for(i=1;i<n;i++){
if(a[i].s<a[i-1].t){
a[i].day=a[i-1].day;
// a[i].s = max(a[i].s, a[i-1].s);
a[i].t = min(a[i].t, a[i-1].t);
}
else{
a[i].day=a[i-1].day+1;
}
}
printf("%d\n",a[n-1].day);
sort(a,a+n,cmp1);
int day=0;
for(i=0;i<n;i++){
if(a[i].day==day){
printf(" %d",a[i].pos);
}
else {
if(day)printf("\n");
printf("%d",a[i].pos);
day++;
}
}
printf("\n");
}
return 0;
}
题意:有n个机器,m个任务。每个机器至多能完成一个任务。对于每个机器,有一个最大运行时间xi和等级yi,对于每个任务,也有一个运行时间xj和等级yj。只有当xi>=xj且yi>=yj的时候,机器i才能完成任务j,并获得500*xj+2*yj金钱。问最多能完成几个任务,当出现多种情况时,输出获得金钱最多的情况。
题解:
将任务已x从大到小排序(x相同时已y从大到小排序)。然后也用相同排序方法排序机器。开始遍历任务,找出所有xi(xi>=xj),从中选择yi最小的一个作为这个任务的运行机器。为什么这么贪心,因为若还存在任务(xk,yk)使得这个机器能被使用,但xj>=xk,所以获得金钱更多,优先选择j;若k不能使用这个机器,那么必定也就不存在其他机器能被使用,除非是新加入的机器,但新加入的必定不能完成任务j,所以完成任务保证了最多。
Problem : 4864 ( Task ) Judge Status : Accepted
RunId : 11142745 Language : C++ Author : Kylers
Code Render Status : Rendered By HDOJ C++ Code Render Version 0.01 Beta
#include<cstdio>
#include<cstring>
#include<map>
#include<iostream>
#include<algorithm>
#define N 100010
using namespace std;
struct ss
{
int xi,yi;
}mat[N],work[N];
bool cmp(ss a,ss b)
{
if(a.xi==b.xi)return a.yi>b.yi;
return a.xi>b.xi;
}
map<int,int>q;
int main()
{
int n,m,i;
while(~scanf("%d%d",&n,&m))
{
for(i=0;i<n;i++)scanf("%d%d",&mat[i].xi,&mat[i].yi);
for(i=0;i<m;i++)scanf("%d%d",&work[i].xi,&work[i].yi);
sort(mat,mat+n,cmp);
sort(work,work+m,cmp);
q.clear();
int j=0;
long long num=0,ans=0;
for(i=0;i<m;i++){
while(j<n&&mat[j].xi>=work[i].xi){
q[mat[j].yi]++;
j++;
}
map<int,int>::iterator it=q.lower_bound(work[i].yi);
if(it!=q.end())
{
num++;
ans+=(500*work[i].xi+2*work[i].yi);
int t=it->first;
q[t]--;
if(q[t]==0)q.erase(t);
}
}
printf("%I64d %I64d\n",num,ans);
}
return 0;
}
ZOJ3778
问题转化一下,就是给定n堆石子,每次最多可以选m堆,每堆里只能取走一个石子,问最快几次取完。
最多的一堆棋子的个数为t,石子总个数为sum。
则
若t*m>=sum,
这时,t-1次内是不能取完所有石子的,故至少需要t次,下面是一种t次取完的做法。
画一个t*m的棋盘(t行m列),把a1从第1列最下角开始,一个一个从下向上地放进第一列,第一个石子放在(t,1),第2个放在
(t-1,1)...然后放a2,a3....当i列放慢,就从(t,i+1)开始从下向上放。
这样,这个棋盘足够容纳所有石子。对任意一堆石子ai,其中的石子要么全在一列,要么在2个相邻的列,列i,列i+1,
同时,因为ai<=t,故ai中的任意2个石子不在同一行。
然后,我们每次取走一行,就能用t步取完。
若t*m<sum,此时令f=sum/m+(sum%m?1:0);
由于(f-1)*m<sum,f*m>=sum
故f-1次内不能取完,而我们可以用f次取完。
首先f>t
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m,i;
int ma=-1,x;
int s=0;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d",&x);
if(x>ma)ma=x;
s+=x;
}
int ans=s/m;
if(s%m)ans++;
if(ma>ans)printf("%d\n",ma);
else printf("%d\n",ans);
}
return 0;
}
有n个问题
2014 Multi-University Training Contest 2
hdu4882ZCC Loves Codefir
题意#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<iostream>
#include<algorithm>
#define N 100010
using namespace std;
struct ss{
int t,k;
}a[N];
int cmp(ss a,ss b){
// return a.k*b.t>b.k*a.t;
return a.t*a.k+(a.t+b.t)*b.k<b.t*b.k+(a.t+b.t)*a.k;
}
int main()
{
int n,i;
while(~scanf("%d",&n))
{
for(i=0;i<n;i++)scanf("%d",&a[i].t);
for(i=0;i<n;i++)scanf("%d",&a[i].k);
sort(a,a+n,cmp);
// for(i=0;i<n;i++)printf("%d %d\n",a[i].t,a[i].k);
long long s=0,tsum=0;
for(i=0;i<n;i++){
tsum+=a[i].t;
s+=tsum*a[i].k;
}
cout<<s<<endl;
}
}
ZOJ3715
题意:
有n个学生要选出班长编号从1到n,1号人比较虚荣,想自己当班长,每个人都可以投一票给自己心目中的人但不能投给自己,只要谁的票数最高谁就可以当班长。给出每个人心目中的投票人,以及贿赂每个人所需要的糖果,(只要你给了那个人一定数目的糖果他就会支持你) 。问1号如果当班长的话,最少需要的糖果数。
思路:
由于这里的n比较小,我们只要枚举1当班长时的得票数x,然后再将其他人的得票数大于x的变为x-1 (减少的给1并且减少的肯定是所需糖果树最少的),然后检查最后1的得票数,如果大于x那么肯定无解,如果等于x,只要保证2到n中有得票数<= x - 2的即可(1要投票给别人)。如果小于x,那么从剩下没有支持1的中,找出所需糖果树最少的来贿赂得票知道等于x为止。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct ss{
int f,c;
}a[110],b[110];
int v[110],vv[110];
int cmp(ss a,ss b){
return a.c<b.c;
}
int main()
{
int t,n,i,j,k;
scanf("%d",&t);
while(t--){
memset(v,0,sizeof(v));
scanf("%d",&n);
for(i=2;i<=n;i++){
scanf("%d",&a[i].f);
v[a[i].f]++;
}
for(i=2;i<=n;i++)scanf("%d",&a[i].c);
sort(a+2,a+n+1,cmp);
int s;
int res=1000000000;
for(i=v[1];i<=n;i++)
{
for(j=2;j<=n;j++){
b[j].f=a[j].f;
b[j].c=a[j].c;
}
for(j=1;j<=n;j++)vv[j]=v[j];
s=0;
for(j=2;j<=n;j++){
if(b[j].f!=1&&vv[b[j].f]>0&&vv[b[j].f]>=i){
// printf("*** %d %d\n",i,j);
s+=b[j].c;
vv[b[j].f]--;
vv[1]++;
b[j].f=1;
}
}
if(vv[1]>i)continue;
if(vv[1]<i) {
for(j=2;j<=n;j++){
if(vv[1]==i)break;
if(b[j].f!=1&&vv[b[j].f]>0){
s+=b[j].c;
vv[b[j].f]--;
vv[1]++;
b[j].f=1;
}
}
}
if(vv[1]==i){
int f=0;
for(j=2;j<=n;j++){
if(vv[j]<i-1){
f=1;
break;
}
}
if(f){
res=min(res,s);
}
}
}
printf("%d\n",res);
}
return 0;
}
ZOJ 3508
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
struct soldier
{
int minw,maxw;
};
bool cmp(soldier a,soldier b)
{
return a.maxw<b.maxw;
}
int main()
{
int n,m,i,x,ans;
soldier t;
while(cin>>n>>m)
{
vector<soldier> v;
for(i=0; i<n; i++)
{
cin>>t.minw>>t.maxw;
v.push_back(t);
}
sort(v.begin(),v.end(),cmp);//以maxw排序
multiset<int> mt;
multiset<int>::iterator it;
for(i=0; i<m; i++)
{
cin>>x;
mt.insert(x);//自动升序排列
}
ans=0;
for(i=0; i<n; i++)
{
it=mt.lower_bound(v[i].minw);//返回不小于 v[i].minw的第一个值的地址
if((it!=mt.end())&&(*it<=v[i].maxw))
{
ans++;
mt.erase(it);
}
}
cout<<ans<<endl;
}
return 0;
}
HDU4883 区间选点
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=24*60;
int dp[N];
int main()
{
int t;
cin>>t;
while(t--)
{
int m,i,val,h1,h2,m1,m2,p1,p2;
char t1[10],t2[10];
memset(dp,0,sizeof(dp));
scanf("%d",&m);
for(i=0;i<m;i++)
{
scanf("%d%s%s",&val,t1,t2);
sscanf(t1,"%d:%d",&h1,&m1);
sscanf(t2,"%d:%d",&h2,&m2);
p1=h1*60+m1;
p2=h2*60+m2;
dp[p1]+=val;
dp[p2]+=-val;
}
int ma=0;
for(i=0;i<24*60;i++){
dp[i]=dp[i-1]+dp[i];
ma=dp[i]>ma?dp[i]:ma;
}
printf("%d\n",ma);
}
return 0;
}
HDU4844
题意,就是有N种炒饭,每次炒的时间是t分钟,每次最多炒k份,然后按照进店的顺序给出m个顾客的信息,进店时间,炒饭的编号以及份数。然后要输出每个顾客离开的时间。
题目中告诉了我们炒饭的规则,按照先来先服务,但是每次炒会炒尽可能多的份数,不过不会有多余的。
举个例子,比如每次可以炒5份,每次5分钟。
第一个顾客08:00进来,点了2份A,
第二个顾客08:04进来,点了3份A。
在08:00开始炒的话,由于这个时候第二个顾客还没进来,所以就只炒2份,第一个顾客在08:05离开,这时才炒第二个的3份,所以第二个离开时间是08:10。
同样是每次可以炒5份,每次5分钟。
第一个顾客08:00进来,点了6份A,
第二个顾客08:01进来,点了5份B,
第三个顾客08:02进来,点了4份A。
同样地,先炒5份给第一个,还差一份,这是已经是08:05了,第三个顾客也进来了,所以这时直接炒5份A(因为会尽可能多地炒),08:10第一个和第三个可以同时离开。接着才炒第二个的。
#include<iostream>
#include<cstdio>
using namespace std;
struct ss
{
int timer, type, num, ans;
}a[1010];
int gettime(char *s)
{
return ((s[0]-'0')*10+s[1]-'0')*60+(s[3]-'0')*10+s[4]-'0';
}
int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
int n,t,k,m,i,j;
char ti[10];
scanf("%d%d%d%d",&n,&t,&k,&m);
for(i=0;i<m;i++)
{
scanf("%s",ti);
a[i].timer=gettime(ti);
scanf("%d%d",&a[i].type,&a[i].num);
}
int now,nnum,tmp;
now=a[0].timer;
for(i=0;i<m;i++)
{
if(!a[i].num)continue;
tmp=now>a[i].timer?now:a[i].timer;
now=tmp+(a[i].num+k-1)/k*t;
nnum=(k-a[i].num%k)%k;
a[i].ans=now;
for(j=i+1;j<m;j++)
{
if(!a[j].num)continue;
if(a[j].timer>now-t||nnum==0)break;
if(a[j].type==a[i].type)
{
if(a[j].num>nnum)
{
a[j].num-=nnum;
nnum=0;
}
else
{
nnum-=a[j].num;
a[j].num=0;
a[j].ans=now;
}
}
}
}
for(i=0;i<m;i++)printf("%02d:%02d\n",(a[i].ans/60)%24,a[i].ans%60);
if(cas)printf("\n");
}
return 0;
}
/*
test:
2
1 9 5 2
00:00 2 7
00:16 2 7
8 1 2 2
00:00 8 3
00:01 8 1
ans:
00:18
00:36
00:02
00:02
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
int T;
char str[1010];
scanf("%d",&T);
while(T--)
{
scanf("%s",str);
int start=0,num=0,step=0;
for(int i=0;str[i];i++)
{
if(str[i]=='*')start++;
else num++;
}
if(start+1>num){
num=start+1-num;
step+=num;
}
else num=0;
start=0;
for(int i=0;str[i];i++)
{
if(str[i]>='0'&&str[i]<='9')num++;
else start++;
if(start+1>num){
start--;
num++;
step++;
}
}
printf("%d\n",step);
}
return 0;
}