codeforces 82D Cinema Cashier dp 队列

来源:互联网 发布:淘宝童装模特招聘 编辑:程序博客网 时间:2024/04/29 08:54

题意:在一个电影院安排座位,观众是组团来的,每个团的观众坐在同一行。买票时可以选位置,所以,先到的团队都会选最好的,输出每个团队的座位。其中有个还是f(x,y)=abs(x-mid)+(y-mid);是每个位置的好坏程度,即距离中心点的距离,越小位置越好

做法:用队列的手法求出每个团队在每一行,每一起点的价值和。然后对于座位上有人的点,加入到队列中,并且适时弹出队列。如果存在队列为空的时刻,那个区域就是符合题意的。具体看代码,双端队列还是不熟练啊。

#include <iostream>#include <deque>#include <cstdio>#include <cstring>#define LMT 102#define eps 1e8using namespace std;bool gra[LMT][LMT];int l,r1,r2,value,wid,mid;deque<int>noq;int vn;int abs(int x){    return x>0?x:-x;}void solve(int vv,int i,int rr1,int rr2){    if(value>=vv)    {        value=vv;l=i;r1=rr1;r2=rr2;    }}int main(){    int n,k;    scanf("%d%d",&n,&k);    mid=(k+1)>>1;    memset(gra,1,sizeof(gra));    while(n--)    {        scanf("%d",&wid);        value=eps;        for(int i=k;i>=1;i--)        {            noq.clear();            vn=0;            if(k<wid)break;            for(int j=k;j>k-wid;j--)            {                if(!gra[i][j])noq.push_back(j);                vn+=abs(i-mid)+abs(j-mid);            }           if(noq.empty())solve(vn,i,k-wid+1,k);            for(int j=k-wid;j>=1;j--)            {               while(!noq.empty()&&(*noq.begin())-wid>=j)noq.pop_front();               if(!gra[i][j])noq.push_back(j);               vn=vn-(abs(i-mid)+abs(j+wid-mid))+abs(i-mid)+abs(j-mid);                    if(noq.empty())solve(vn,i,j,j+wid-1);            }        }            if(value<eps)            {                printf("%d %d %d\n",l,r1,r2);                for(int i=r1;i<=r2;i++)gra[l][i]=0;            }            else printf("-1\n");    }    return 0;}