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;
}