紫书 例6-1 并行程序模拟(Concurrency Simulator,ACM/ICPC World Finals 1991,UVA210)

大家好,我是小黄呀。

VJ题目传送门

题目大意

题目给出n个程序,其中每个程序包含若干条指令,每条指令执行所需时钟周期,给出每个程序拥有的总共时钟周期数,模拟出程序执行的过程,输出相应的信息。

五条指令如下:

  • var = constant:赋值,其中var为单个小写字母表示,初始为0,是全局变量。constant为小于100的非负整数,是常数。
  • print var:打印
  • lock:上锁,独占资源。
  • unlock:解锁
  • end:程序结束

程序模拟过程中存在两个队列:

  • rq:等待队列,按此队列依次执行
  • rb:阻止队列,当程序1执行lock时,若程序2再次执行lock,则将程序2放入rb队列中,直到程序执行unlock后,再将rb队列的队首插入到rq队列队首

思路分析

由于lock和unlock指令的具体执行过程,违反了基本队列的规则,具体有两种方法。

  1. 自定义一个支持“首部插入”的队列
  2. 利用STL中的双端队列deque

具体代码及分析

  1. 方法一:自定义一个支持“首部插入”的队列
    1. template<class T1,class T2> struct pair:pair可以将两个类合二为一,成为一组数据,相当于一个结构体。更多详细内容
#include<bits/stdc++.h>
#define CLOSE() ios::sync_with_stdio(false)
#define CLEAR(a,b) memset(a,b,sizeof(a))
#define IN() freopen("in.txt","r",stdin)
#define OUT() freopen("out.txt","w",stdout)
using namespace std;

const int maxn=1e3;
using LL=long long;
using UI=unsigned int ;

//-----------------------------------------
vector<vector<string> >prog;
vector<pair<int,int> > rf;
int readyq[maxn],rrear,rfront;
int blocked[maxn],brear,bfront;

int main()
{
    #ifdef _DEBUG
        IN();
        OUT();
    #endif // _DEBUG

    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,time[5],qutm;//n个程序,每条指令所需的时钟周期,总时钟周期
        scanf("%d",&n);
        for(int i=0;i<5;++i)
            scanf("%d",&time[i]);
        scanf("%d",&qutm);
        getchar();
        prog.clear();
        rf.clear();
        CLEAR(readyq,0);
        rrear=rfront=0;
        for(int i=0;i<n;i++)//存入每个程序的指令
        {
            readyq[rfront++]=i;
            string s;
            while(getline(cin,s))
            {
                prog.push_back(vector<string>());
                rf.push_back(make_pair(0,0));
                prog[i].push_back(s);
                if(s=="end")break;
            }
        }
        CLEAR(blocked,0);
        brear=bfront=0;
        map<char,int> vari;
        bool lock=false;
        while(rrear!=rfront)//准备队列非空
        {
            int nowprog = readyq[rrear++]; 
            readyq[rfront++] = nowprog;
			//printf("now = %d\n", nowprog+1);
			int t = qutm;
			while (t > 0) //在时间范围内
                {
				string inst = prog[nowprog][rf[nowprog].first++];
				int p = inst.find('='), p2 = inst.find("print");
				if (inst == "end") {
					rfront--;
					break;
				}
				else if (p != -1) {
					vari[inst[p - 2]] = atoi(inst.substr(p + 2).c_str());
					t -= time[0];
				}
				else if (p2 != -1) {
					char va = inst[p2 + 6];
					printf("%d: %d\n", nowprog + 1, vari[va]);
					t -= time[1];
				}
				else if (inst == "lock") {
					if (!lock) {
						lock = true;
						t -= time[2];
					}
					else {
						rfront--;
						blocked[bfront++] = nowprog;
						rf[nowprog].first--;
						break;
					}
				}
				else {
					t -= time[3];
					lock = false;
					if (brear != bfront) {
						readyq[--rrear] = blocked[brear++];
					}
				}
			}
		}
		if (T) puts("");
	}
	return 0;
}




  1. 方法二:STL中的双端队列deque(先贴的最简洁的,但不好懂)
    1. string::nops:作为string的成员函数的一个长度参数时,表示“直到字符串接受结束”。更多详细内容
    2. getsfgetsgets函数没有指定输入字符大小,会无限读取,一旦输入的字符大于数据长度会发生内存越界。fgets函数最多只能读入n-1个字符,读入结束后,系统自动在最后加‘\0’,并以str作为函数值返回。更多详细内容
#include<bits/stdc++.h>
using namespace std;

const int maxn=1e3;

int T,a[7];//测试用例个数,输入的第二行所给起始条件

string s,ans;

int main()
{
    cin>>T;
    for(int i=0;i<T;i++)
    {
        for(int j=0;j<7;j++)
            scanf("%d",&a[j]);
        getchar();//吸收多余字符
        queue<string> q1[a[0]];//每个程序对应的指令
        deque<int> qr;//等待队列
        queue<int> qb;//阻止队列
        for(int j=0;j<a[0];j++)//存入n个程序
        {
            while(getline(cin,s)&&s!="end")
                q1[j].push(s);
            qr.push_back(j);
        }


    if(i!=0)//连续输出的空行
        puts("");
    map<string,string> vmp;//变量对应的值
    bool isLock=false;//标记是否上锁
    while(!qr.empty())//判断等待队列非空
    {
        int t=0,k=qr.front();//t为已消耗的时长,k为当前程序的编号
        qr.pop_front();
        bool isBlock=false;//标记是否发生上锁未解开
        while(t<a[6]&&!q1[k].empty())//判断未超时
        {
            s=q1[k].front();//取首指令
            int j=s.find('=');
            if(j!=string::npos)//赋值
            {
                vmp[s.substr(0,j-1)]=s.substr(j+2);
                t+=a[1];
            }
            else
            {
                j=s.find(' ');
                if(j!=string::npos)//打印并输出
                {
                    ans="0";
                    if(vmp[s.substr(j+1)]!="")
                        ans=vmp[s.substr(j+1)];
                    printf("%d: %s\n",k+1,ans.c_str());
                    t +=a[2];
                }
                else
                {
                    if(s[0]=='l')//lock
                    {
                        if(!isLock)
                        {
                            isLock=true;
                            t+=a[3];
                        }
                        else//已上锁
                        {
                            qb.push(k);//加入阻止队列尾部
                            isBlock = true;//上锁
                            break;//跳出
                        }
                    }
                    else if(s[0]=='u')//unlock
                    {
                        isLock = false;//解锁
                        if(!qb.empty())//阻止队列非空
                        {
                            qr.push_front(qb.front());//阻止队列首部加入等待队列首部
                            qb.pop();
                        }
                        t+=a[4];
                    }
                }
            }
            q1[k].pop();
        }
        if(!q1[k].empty()&&isBlock)//再次加入等待队列等待
        {
            qr.push_back(k);
        }
    }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
我想将frontend 也是用volumes,将其映射到/app/frontend目录,在/app/frontend下install以及build,如何实现 docker-compose.yml文件: version: '3' services: frontend: build: context: ./frontend dockerfile: Dockerfile ports: - 8010:80 restart: always backend: build: context: ./backend dockerfile: Dockerfile volumes: - /app/backend:/app environment: - CELERY_BROKER_URL=redis://redis:6379/0 command: python manage.py runserver 0.0.0.0:8000 ports: - 8011:8000 restart: always celery-worker: build: context: ./backend dockerfile: Dockerfile volumes: - /app/backend:/app environment: - CELERY_BROKER_URL=redis://redis:6379/0 command: celery -A server worker -l info --pool=solo --concurrency=1 depends_on: - redis - backend restart: always celery-beat: build: context: ./backend dockerfile: Dockerfile volumes: - /app/backend:/app environment: - CELERY_BROKER_URL=redis://redis:6379/0 command: celery -A server beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler depends_on: - redis - backend restart: always redis: image: redis:latest ports: - 6379:6379 restart: always mysql: image: mysql:latest environment: - MYSQL_ROOT_PASSWORD=sacfxSql258147@ ports: - 8016:3306 volumes: - ./mysql:/var/lib/mysql restart: always frontend:dockerfile文件 FROM node:16.18.1 WORKDIR /app/frontend COPY package*.json ./ RUN npm install COPY . . RUN npm run build:prod FROM nginx:latest COPY --from=0 /app/frontend/dist/ /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
最新发布
07-14

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_AoSnow_

创作不易,打赏打赏些8

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值