貪心算法

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

題意 
有n個問題
第二行爲解決每個問題需要的時間t
第三行爲解決每個問題的係數k
t總*k及解決每個問題的罰時數,要求總罰時最少
對問題進行兩兩比較,把罰時小的放前面
另外杭電上有點坑,用%lld輸出吃了wa
代碼:
#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
*/


zoj3829 貪心
http://www.cnblogs.com/whatbeg/p/4024974.html

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








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章