1. 程式人生 > >優先佇列集錦(其實都是水題啦)

優先佇列集錦(其實都是水題啦)

1 HDU-1873   水題,基本優先佇列。 

#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;
struct node
{
    int lev;
    int ord;
    bool friend operator < (const node a,const node b)
    {
       if(a.lev!=b.lev)return a.lev < b.lev;
       else return a.ord > b.ord;
    }
};
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        char s[5];
        priority_queue<node> doc[4];
        for(int i=1;i<=3;i++)
        {
            while(!doc[i].empty()) doc[i].pop();
        }
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            struct node now;
            scanf("%s",s);
            if(s[0]=='I')
            {
                int a,b;
                now.ord=++cnt;
                scanf("%d%d",&a,&b);
                now.lev=b; doc[a].push(now);
            }
            else
            {
                int a;
                scanf("%d",&a);
                if(!doc[a].empty())
                {
                    now=doc[a].top();
                    doc[a].pop();
                    printf("%d\n",now.ord);
                }
                else printf("EMPTY\n");
            }
        }
    }
    return 0;
}

2 POJ-1442

用兩個優先佇列,一個是K個從大到小(佇列首就是第K小數字),另一個隊裡從小到大是儲存其他的數字(佇列頂是其他個最小的元素)

進行如下操作

A 如果第一個佇列未滿K個直接扔進去

B 如果滿K個則每次直接扔到另一個佇列,將另一個佇列的佇列首和第一個佇列首比較,如果小的話,pop第一個佇列,把第二個佇列首放進去。

#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
int num[30100];
int ord[30100];
int ans[30100];

int main()
{
    priority_queue<int,vector<int>,greater<int> > res;
    priority_queue<int> aim;

    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++) scanf("%d",&num[i]);
    for(int i=0;i<m;i++) scanf("%d",&ord[i]);
    int cnt=0;
    for(int i=0;i<m;i++)
    {
        int pos=i+1;
        int temp=ord[i];
        for(;cnt<temp;cnt++)
        {
            res.push(num[cnt]);
        }
        while(aim.size()<pos)
        {
            int a; a=res.top();res.pop();
            aim.push(a);
        }
        while(!res.empty()&&!aim.empty()&&res.top()<aim.top())
        {
            int a=res.top(),b=aim.top();
            res.pop(); aim.pop();
            aim.push(a); res.push(b);
        }
        ans[i]=aim.top();
    }
    for(int i=0;i<m;i++) printf("%d\n",ans[i]);
    return 0;
}

POJ 2312. 

BFS,因為每次拓展的結果不一定是最小的,如果這塊有牆,那麼從這個點出發進行拓展的答案有可能錯誤,所以需要優先拓展步數小的節點。

#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;

char map[350][350];
bool vis[350][350];
int dir[4][2]={1,0 ,-1,0 ,0,1, 0,-1};
int n,m;
struct node
{
    int x,y;
    int step;
    bool friend operator < (const node a,const node b)
    {
        return a.step>b.step;
    }
};

bool jud(struct node a)
{
    if(a.x<1||a.y<1||a.x>n||a.y>m) return 0;
    return 1;
}

void bfs(int sx,int sy)
{
    struct node u,v;
    u.x=sx;u.y=sy;
    u.step=0;
    vis[sx][sy]=1;
    priority_queue<node> que;
    que.push(u);
    while(!que.empty())
    {
       u=que.top();
       que.pop();
       if(map[u.x][u.y]=='T')
       {
           printf("%d\n",u.step);
           return;
       }
       for(int i=0;i<4;i++)
       {
            v.x=u.x+dir[i][0];v.y=u.y+dir[i][1];
            if(jud(v)&&!vis[v.x][v.y]&&map[v.x][v.y]!='S'&&map[v.x][v.y]!='R')
            {
                vis[v.x][v.y]=1;
                v.step=u.step+1;
                if(map[v.x][v.y]=='B') v.step++;
                que.push(v);
            }
       }
    }
    printf("-1\n");
    return;
}


int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0||m==0) break;
        int sx,sy;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf(" %c",&map[i][j]);
                if(map[i][j]=='Y') {sx=i;sy=j;}
            }
        }
        bfs(sx,sy);
    }
    return 0;
}

HDU 4006

水題,上面講過這種題,直接上程式碼了。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        priority_queue<int ,vector<int>,greater<int> >que;
        while(!que.empty()) que.pop();
        int cnt=0;
        for(int i=0;i<n;i++)
        {
            char s[5];
            scanf("%s",s);
            if(s[0]=='I')
            {
                int a;
                scanf("%d",&a);
                if(cnt==k)
                {
                    if(que.top()<a)
                    {
                        que.pop(); que.push(a);
                    }
                    else continue;
                }
                else { que.push(a); cnt++;}
            }
            else
            {
                printf("%d\n",que.top());
            }

        }
    }
    return 0;
}

HDU 1509

水題

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct node
{
    char s[50];
    int date;
    int pro;
    int order;
    bool friend operator < (const node a, const node b)
    {
        if(a.pro!=b.pro) return a.pro > b.pro;
        else return a.order > b.order ;
    }
};
int main()
{
    priority_queue<node> que;
    char s[20];
    int cnt=0;
    while(scanf("%s",s)!=EOF)
    {
        if(s[0]=='P')
        {
            struct node t;
            scanf("%s%d%d",t.s,&t.date,&t.pro);
            t.order=cnt;
            cnt++;
            que.push(t);
        }
        else
        {
          if(!que.empty())
          {
              struct node t;
              t=que.top() ; que.pop();
              printf("%s %d\n",t.s,t.date);
          }
          else
          {
              printf("EMPTY QUEUE!\n");
          }
        }
    }
    return 0;
}

HDU1896

模擬一下就好。原來做過的題

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct node
{
    int pos;
    int trow;
    bool friend operator < (const node a,const node b)
    {
        if(a.pos!=b.pos) return a.pos>b.pos;
        else return a.trow>b.trow;
    }
};
int main()
{
    int T;
    scanf("%d",&T);
    for(int tt=0;tt<T;tt++)
    {
        int n;
        scanf("%d",&n);
        priority_queue<node> que;
        while(!que.empty()) que.pop();
        for(int i=0;i<n;i++)
        {
           struct node a;
           scanf("%d%d",&a.pos,&a.trow);
           que.push(a);
        }

        int ans=0,cnt=1;

        while(!que.empty())
        {
            if(cnt%2)
            {
               struct node x;
               x=que.top();
               x.pos+=x.trow;
               que.pop();
               que.push(x);
               ans=x.pos;
            }
            else
            {
                 ans=que.top().pos;
                 que.pop();
            }
            cnt++;
        }
        printf("%d\n",ans);
    }
    return 0;
}
HDU 1242

逆向BFS,從公主的位置出發去找最近的朋友即可

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
struct node
{
    int x,y,step;
    bool friend operator < (const node a,const node b)
    {
        return a.step > b.step;
    }
};

char  map[222][222];
bool vis[222][222];
int dir[4][2]={1,0 ,-1,0 ,0,1,0,-1};
int n,m,sx,sy;

bool j(struct node a)
{
    if(a.x<1||a.y<1||a.x>n||a.y>m) return 0;
    return 1;
}

void bfs(int sx,int sy)
{
    priority_queue<node> que;
    while(!que.empty()) que.pop();
    memset(vis,0,sizeof(vis));

    struct node u,v;
    u.x=sx; u.y=sy; u.step=0;
    vis[sx][sy]=1;
    que.push(u);
    while(!que.empty())
    {
      u=que.top();que.pop();
      if(map[u.x][u.y]=='r')
      {
          printf("%d\n",u.step);
          return;
      }
       for(int i=0;i<4;i++)
       {
          v.x=u.x+dir[i][0];
          v.y=u.y+dir[i][1];
          v.step=u.step+1;
          if(j(v)&&!vis[v.x][v.y]&&map[v.x][v.y]!='#')
          {
             vis[v.x][v.y]=1;
             if(map[v.x][v.y]=='x') v.step+=1;
             que.push(v);
          }
       }
    }
    printf("Poor ANGEL has to stay in the prison all his life.\n");
    return;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            scanf(" %c",&map[i][j]);
            if(map[i][j]=='a') {sx=i;sy=j;}
        }
    }
    bfs(sx,sy);
    }
    return 0;
}

HDU4393

這道題剛開始一直wa,後來看了題解。直接開個speed100的優先佇列(第一秒的速度優先),每次迴圈一遍找出最遠的即可

#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
struct node
{
   int pos,ord;
   bool friend operator < (const node a,const node b)
   {
       if(a.pos!=b.pos ) return a.pos<b.pos;
       else return a.ord>b.ord;
   }
};

int ans[50020];
priority_queue<node> a[105];
int main()
{
    int T;
    scanf("%d",&T);
    for(int tt=1;tt<=T;tt++)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            struct node x;
            int sp;
            scanf("%d%d",&x.pos,&sp);
            x.ord=i;
            a[sp].push(x);
        }
        for(int i=0;i<n;i++)
        {
            int ma=0,pos=50001,kpos=0;
            for(int j=1;j<=100;j++)
            {
               if(a[j].empty()) continue;
               else
               {
                  if( i*j+a[j].top().pos>ma||(i*j+a[j].top().pos==ma&&pos>a[j].top().ord))
                  {
                       ma= i*j+a[j].top().pos ; pos=a[j].top().ord;kpos=j;
                  }
               }
            }
            a[kpos].pop();
            ans[i]=pos;
        }
        printf("Case #%d:\n",tt);
        printf("%d",ans[0]);
        for(int i=1;i<n;i++)
        {
            printf(" %d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}

POJ 2431 思路和上面的一模一樣
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
priority_queue<int> que[102];
int n;
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<=100;i++)
        {
            while(!que[i].empty()) que[i].pop();
        }
        for(int i=0;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            que[b].push(a);
        }
        int dis,ful;
        scanf("%d%d",&dis,&ful);
        dis-=ful;ful=0;
        int ans=0;
        while(1)
        {
            if(dis<=0) break;
            int pos=-1;
            for(int i=100;i>0;i--)
            {
                if(que[i].empty()) continue;
                if(que[i].top()>=dis) {pos=i;break;}
            }
            if(pos<0) break;
            else
            {
                ans++;
                dis-=pos;
                que[pos].pop();
            }
        }
        if(dis<=0)
        {
            printf("%d\n",ans);
        }
        else printf("%d\n",-1);
    }
    return 0;
}

POJ2970

自己是用 第一優先順序截止日期,第二優先順序bi/ai(大到小) 第三優先順序bi 來做的,優先填滿最貴的。結果錯了 。因為有可能兩個較便宜的比一個貴的還貴

然後看了網上的思路

很明顯,如果手頭這個工作無法完成,那麼我們就需要在已經完成的工作中(這裡其實包括手頭的工作)找到那個a最大的工作,然後給錢來減少那個工作所需的時間,以便以最小的花銷來完成現在所有的工作。所以我們需要一個優先佇列來維護當前擁有最大a的那個工作。我們可以直接呼叫stl裡的priority_queue來完成這個工作,每次取出a最大的工作,如果這項工作已經不能再給錢了,那麼就將其POP出佇列,選取下一個,直到我們可以再deadline前完成手頭的工作。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct node
{
    int di,ai,bi,rest;
    double val;
    bool friend operator < (const node a,const node b)
    {
        return a.ai<b.ai;
    }
}test[101000];

bool cmp (const node a,const node b )
{
    return a.di < b.di;
}

priority_queue<node> que;
int n;
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        while(!que.empty()) que.pop();
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d",&test[i].ai,&test[i].bi,&test[i].di);
            test[i].val=1.00000*test[i].bi;
            test[i].val=test[i].val/test[i].ai;
            test[i].rest=test[i].bi;
        }
        sort(test,test+n,cmp);
        int time=0;
        double ans=0;
        for(int i=0;i<n;i++)
        {
            que.push(test[i]);
            time+=test[i].bi;
            if(time<=test[i].di) continue;
            else
            {
                while(1)
                {
                    if(time<=test[i].di) break;
                    struct node a;
                    a=que.top(); que.pop();
                    int need=time-test[i].di;
                    if(need>=a.rest)
                    {
                      double temp=a.rest*1.000000;
                      temp/=(1.000000*a.ai);
                      ans+=temp; time-=a.rest; continue;
                    }
                    else
                    {
                        a.rest-=need;
                        double temp=need*1.000000;
                        temp/=(1.0000000*a.ai);
                        ans+=temp; time=test[i].di;
                        que.push(a);
                        break;
                    }
                }
            }
        }
        printf("%.2f\n",ans);
    }
    return 0;
}

總的來說這兩天做的優先佇列,質量都不高,以練手為主吧。(其實是因為太忙了,沒時間想難題。。。。。)