模拟

CODEVS1156作业调度方案

 题目描述 Description

我们现在要利用m台机器加工n个工件,每个工件都有m道工序,每道工序都在不同的指定的机器上完成。每个工件的每道工序都有指定的加工时间。

每个工件的每个工序称为一个操作,我们用记号j-k表示一个操作,其中j为1到n中的某个数字,为工件号;k为1到m中的某个数字,为工序号,例如2-4表示第2个工件第4道工序的这个操作。在本题中,我们还给定对于各操作的一个安排顺序。

例如,当n=3,m=2时,“1-1,1-2,2-1,3-1,3-2,2-2”就是一个给定的安排顺序,即先安排第1个工件的第1个工序,再安排第1个工件的第2个工序,然后再安排第2个工件的第1个工序,等等。

一方面,每个操作的安排都要满足以下的两个约束条件。

(1) 对同一个工件,每道工序必须在它前面的工序完成后才能开始;

(2) 同一时刻每一台机器至多只能加工一个工件。

另一方面,在安排后面的操作时,不能改动前面已安排的操作的工作状态。

由于同一工件都是按工序的顺序安排的,因此,只按原顺序给出工件号,仍可得到同样的安排顺序,于是,在输入数据中,我们将这个安排顺序简写为“1 1 2 3 3 2”。

还要注意,“安排顺序”只要求按照给定的顺序安排每个操作。不一定是各机器上的实际操作顺序。在具体实施时,有可能排在后面的某个操作比前面的某个操作先完成。

例如,取n=3,m=2,已知数据如下:

则对于安排顺序“1 1 2 3 3 2”,下图中的两个实施方案都是正确的。但所需要的总时间分别是10与12。

当一个操作插入到某台机器的某个空档时(机器上最后的尚未安排操作的部分也可以看作一个空档),可以靠前插入,也可以靠后或居中插入。为了使问题简单一些,我们约定:在保证约束条件(1)(2)的条件下,尽量靠前插入。并且,我们还约定,如果有多个空档可以插入,就在保证约束条件(1)(2)的条件下,插入到最前面的一个空档。于是,在这些约定下,上例中的方案一是正确的,而方案二是不正确的。

显然,在这些约定下,对于给定的安排顺序,符合该安排顺序的实施方案是唯一的,请你计算出该方案完成全部任务所需的总时间。

思路:模拟。读入数据后,简单的进行模拟。不过还是多交了好几遍,就是因为开小了数组范围。
#include<iostream>
#include<cstdio>
using namespace std;
int eng[21][21]={0},ti[21][21]={0},st[500]={0},last[21]={0},pre[21]={0};
bool timm[21][10000]={false};
int find(int x,int xx,int y)
{
int i,j;
bool ff=false,fi=false;
i=last[x];
while (!ff)
{
fi=false;
for (j=i;j<i+ti[x][xx];++j)
{
if (timm[y][j])
{
i=j;
while (timm[y][i]) ++i;
fi=true;
break;
}
}
if (!fi) ff=true;
}
return i;
}
int main()
{
int n,m,i,j,t,ans=0;
cin>>m>>n;
for (i=1;i<=n*m;++i)
  cin>>st[i];
for (i=1;i<=n;++i)
  for (j=1;j<=m;++j)
    cin>>eng[i][j];
for (i=1;i<=n;++i)
  for (j=1;j<=m;++j)
    cin>>ti[i][j];
for (i=1;i<=n*m;++i)
{
++pre[st[i]];
t=find(st[i],pre[st[i]],eng[st[i]][pre[st[i]]]);
for (j=t;j<t+ti[st[i]][pre[st[i]]];++j)
timm[eng[st[i]][pre[st[i]]]][j]=true;
last[st[i]]=t+ti[st[i]][pre[st[i]]];
}
for (i=1;i<=n;++i)
  ans=max(ans,last[i]);
cout<<ans<<endl;
} 
View Code

bzoj1033 ZJOI杀蚂蚁

题目大意:根据给定题意模拟游戏过程。

思路:相对比较清晰的大模拟。但因为第一次写这种大模拟,所以还是调试了很久。总结一下这次犯的很多错误:

        1)蚂蚁出生的时候不仅要满足场上不到6只蚂蚁的要求,还要满足(0,0)这个位置没有东西;

        2)在激光塔对拿蛋糕的目标攻击的时候,可能会攻击蚂蚁到线段距离<=0.5(直径为1,半径为0.5)的蚂蚁,这里的判断要十分注意。满足点在端点之间,并且点到直线的距离<=0.5;如果不是对拿蛋糕的目标攻击,就只需要攻击这一个就行了,别的都不符合(按线段式攻击也对,这样会快一些);

        3)在移动的时候,如果这个蚂蚁不能移动,就要把他的上一秒位置统一成这一秒的;

        4)蚂蚁死的时候,会改变队列的头,所以如果平移的这个蚂蚁是target的时候,也要相应的改变target。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxnode 200005
#define inf 2100000000LL
using namespace std;
struct use{
    int old,rank,blood,x,y,ux,uy;
    bool antcake;
}que[maxnode]={0};
int d,r,n,m,s,head,tail,pao[25][2]={0},map[10][10][2]={0},dx[4]={0,1,0,-1},dy[4]={1,0,-1,0},target;
bool cake=false,win=false;
void burn()
{
    que[++tail].old=1;que[tail].rank=(tail+5)/6;que[tail].blood=int(4*pow(1.1,que[tail].rank));
    que[tail].x=que[tail].y=0;que[tail].ux=que[tail].uy=-1;map[0][0][0]=1;que[tail].antcake=false;
}
void leavemessage()
{
    int i,j;
    for (i=head;i<=tail;++i)
        map[que[i].x][que[i].y][1]+=(que[i].antcake ? 5 : 2);
}
bool canmove(int i,int xx,int yy)
{
    if (xx<0||xx>n||yy<0||yy>m) return false;
    if (map[xx][yy][0]==1||(xx==que[i].ux&&yy==que[i].uy)) return false;
    return true;
}
void move()
{
    int i,j,k,maxn,xx,yy;
    for (i=head;i<=tail;++i)
    {
        maxn=-1;
        for (k=0;k<=3;++k)
        {
            xx=que[i].x+dx[k];yy=que[i].y+dy[k];
            if (canmove(i,xx,yy)&&map[xx][yy][1]>maxn) maxn=map[xx][yy][1];
        }
        if (maxn>=0)
        {
            for (k=0;k<=3;++k)
            {
                xx=que[i].x+dx[k];yy=que[i].y+dy[k];
                if (canmove(i,xx,yy)&&map[xx][yy][1]==maxn) break;
            }
            if (que[i].old%5==0)
            {
                k=(k==0?3:k-1);
                while(1)
                {
                    xx=que[i].x+dx[k];yy=que[i].y+dy[k];
                    if (canmove(i,xx,yy)) break;k=(k==0?3:k-1);
                }
            }
            map[que[i].x][que[i].y][0]=0;map[xx][yy][0]=1;
            que[i].ux=que[i].x;que[i].uy=que[i].y;
            que[i].x=xx;que[i].y=yy;
        }
        else {que[i].ux=que[i].x;que[i].uy=que[i].y;}
        if (que[i].x==n&&que[i].y==m&&!cake)
        {
            cake=true;que[i].antcake=true;target=i;k=(int)(4*pow(1.1,que[i].rank));
            que[i].blood=min(k,que[i].blood+k/2);
        }
    }
}
//i炮塔 j蚂蚁 
int fang(int i){return i*i;}
int dis(int i,int j)
{
    int x1,y1,x2,y2;
    x1=pao[i][0];y1=pao[i][1];x2=que[j].x;y2=que[j].y;
    return fang(x1-x2)+fang(y1-y2);
}
bool canattack(int i,int j)
{
    if (dis(i,j)<=r) return true;
    else return false;
}
int disy(int i,int a,int b,int c){return fang(a*que[i].x+b*que[i].y+c);}
void attackone(int i,int j,int kk)
{
    int k,a,b,c,x1,y1,x2,y2;
    if (kk==1) que[j].blood-=d;
    else
    {
      x1=pao[i][0];y1=pao[i][1];x2=que[j].x;y2=que[j].y;
      a=y2-y1;b=x1-x2;c=y1*x2-y2*x1;
      for (k=head;k<=tail;++k)
        if (disy(k,a,b,c)*4<=fang(a)+fang(b)&&
           ((que[k].x>=x1&&que[k].x<=x2)||(que[k].x>=x2&&que[k].x<=x1))&&
           ((que[k].y>=y1&&que[k].y<=y2)||(que[k].y>=y2&&que[k].y<=y1))) 
            que[k].blood-=d;
    }
}
void die(int i)
{
    int j;
    if (target==i){target=0;cake=false;}
    map[que[i].x][que[i].y][0]=0;++head;
    for (j=i;j>=head;--j) {que[j]=que[j-1];if (target==j-1) target=j;}
}
void attack()
{
    int i,j,minn,mini;bool use[25]={false};
    if (target>0)
        for (i=1;i<=s;++i)
            if (canattack(i,target)) {attackone(i,target,0);use[i]=true;}
    for (i=1;i<=s;++i)
        if (!use[i])
        {
            minn=inf;mini=0;use[i]=true;
            for (j=head;j<=tail;++j)
                if (canattack(i,j))
                    if (dis(i,j)<minn){minn=dis(i,j);mini=j;}
            if (mini>0) attackone(i,mini,1);
        }
    for (i=head;i<=tail;++i) 
      if (que[i].blood<0) die(i);
}
void after()
{
    int i,j;
    for (i=head;i<=tail;++i)
        if (que[i].x==0&&que[i].y==0&&que[i].antcake) {win=true;return;}
    for (i=0;i<=n;++i)
      for (j=0;j<=m;++j)
        map[i][j][1]=max(0,map[i][j][1]-1);
    for (i=head;i<=tail;++i) ++que[i].old;
}
void work()
{
    if (tail-head+1<6&&map[0][0][0]==0) burn();
    leavemessage();move();attack();after();
}
int main()
{
    int i,j,t;
    scanf("%d%d%d%d%d",&n,&m,&s,&d,&r);r=r*r;
    for (i=1;i<=s;++i)
    {scanf("%d%d",&pao[i][0],&pao[i][1]);map[pao[i][0]][pao[i][1]][0]=1;}
    scanf("%d",&t);head=1;tail=0;target=0;
    for (i=1;i<=t;++i)
    {
        work();if (win) break;
    }
    if (win) printf("Game over after %d seconds
",i);
    else printf("The game is going on
");
    printf("%d
",tail-head+1);
    for (i=head;i<=tail;++i)
        printf("%d %d %d %d %d
",que[i].old-1,que[i].rank,que[i].blood,que[i].x,que[i].y);
}
View Code

cogs284 内存分配

题目大意:模拟内存的分配。给定内存的大小和一些请求(开始的时间、占用内存、占用时间),如果当前时间不能满足请求,就把它放进队列中(队首元素优先级最高),尽量往前放请求。输出完成所有请求的时间和放进队列的请求个数。

思路:用链表模拟这个过程就可以了,用链表存下相连的空间;用优先队列维护正在用的请求,以便释放。在读入一个请求的时候,把优先队列里时间比当前时间小的全都释放空间,同时根据时间放入队列中的元素,但是要注意,优先队列中相同时间要都释放后在管队列里的请求。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxnode 10005
using namespace std;
struct Node{
    Node *ne;
    int ti,la;
    Node(int ti,int la):ti(ti),la(la) {ne=NULL;}
}*root;
struct use{
    int ten,st,en;
    bool operator < (const use &x)const
    {
        return ten>x.ten;
    }
};
int que[maxnode][2]={0},n;
priority_queue<use> q;
void release(use x)
{
    Node *o,*q;
    o=root;
    while(o->ne != NULL)
    {
        if (o->ne->ti > x.en)
        {
            q=new Node(x.st,x.en);
            q->ne=o->ne;o->ne=q;
            while(q->ne!=NULL)
            {
                if (q->la+1 == q->ne->ti&&q->ne->ti != n+1)
                {
                    q->la=q->ne->la;q->ne=q->ne->ne;
                }
                else break;
            } q=o;
            if (q->la+1 == q->ne->ti&&q->ne->ti != n+1)
            {
                q->la=q->ne->la;q->ne=q->ne->ne;
            }
            break;
        }
        o=o->ne;
    }
}
bool give(int m,int t,int i)
{
    Node *o;int j;
    o=root;
    while(o->ne!=NULL)
    {
        if (o->ne->la - o->ne->ti + 1>=m)
        {
            j=o->ne->ti;
            o->ne->ti=o->ne->ti + m;
            if (o->ne->ti > o->ne->la) o->ne=o->ne->ne;
            q.push((use){i+t,j,j+m-1});
            return true;
        }
        else o=o->ne;
    }
    return false;
}
void print(Node *o)
{
    if (o==NULL) return;
    printf("%d %d
",o->ti,o->la);print(o->ne);
}
int main()
{
    freopen("memory.in","r",stdin);
    freopen("memory.out","w",stdout);
    
    int i,j,t,m,p,head,tail,ans=0,tt;use xx;
    bool f;
    scanf("%d",&n);head=1;tail=0;
    root=new Node(0,-1);root->ne=new Node(1,n);
    root->ne->ne=new Node(n+1,n);
    while(scanf("%d%d%d",&t,&m,&p)==3)
    {
        f=(t==0&&m==0&&p==0);
        while(!q.empty())
        {
            xx=q.top();
            if (xx.ten<=t||f)
            {
                tt=xx.ten;
                while(xx.ten==tt)
                {
                    release(xx);q.pop();ans=max(ans,xx.ten);
                    if (q.empty()) break;
                    xx=q.top();
                }
                while (head<=tail&&give(que[head][0],que[head][1],tt)) ++head;
            }
            else break;
        }
        if (f) break;
        if (!give(m,p,t)) {que[++tail][0]=m;que[tail][1]=p;}
    }
    printf("%d
%d
",ans,tail);
}
View Code
原文地址:https://www.cnblogs.com/Rivendell/p/4644265.html