模拟
CODEVS1156作业调度方案
我们现在要利用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; }
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\n",i); else printf("The game is going on\n"); printf("%d\n",tail-head+1); for (i=head;i<=tail;++i) printf("%d %d %d %d %d\n",que[i].old-1,que[i].rank,que[i].blood,que[i].x,que[i].y); }
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\n",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\n%d\n",ans,tail); }