201903-4 消息传递接口
题目
思路
40分运行错误,待更。
用队列数组储存各个进程的指令。从任意进程的队首指令开始,递归查找能匹配的指令,查到便将该指令对出列。
(2019.9.12)
读数的时候出错了。。。想当然把指令编号当成1位。(逃
这么做效率挺低的,多了很多重复查找。
更好的方法是,让刚执行完一对指令的进程优先执行下一条指令。
AC代码如下
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct comand{
int x;
bool flag;
};
queue<comand> cmd[10005];
int n,T;
bool vis[10005];
bool unlocked(int i,int x,bool f){//递归查找可执行的指令
if(vis[x]) return false;//避免绕圈
vis[x]=true;
if(!cmd[x].empty()){
int t=cmd[x].front().x;
bool ff=cmd[x].front().flag;
if(t==i){
if(ff==f) return false;//指令不匹配
cmd[i].pop();//找到可执行的指令,弹出
cmd[x].pop();
return true;
}
return unlocked(x,t,ff);//递归找下一个
}
return false;//没有与之配对的指令
}
int main(){
scanf("%d%d",&T,&n);
getchar();
while(T--){
for(int i=0;i<n;i++){//输入
while(!cmd[i].empty()) cmd[i].pop();//注意要把队列清空
char c=getchar();//读入'S'、'R'
while(c!='\n'){
int x=0;
char d=getchar();
while(d>='0'&&d<='9'){//读入x
x=x*10+d-'0';
d=getchar();
}
cmd[i].push((comand){x,(c=='S')});//存指令
if(d==-1||d=='\n') break;
c=getchar();//读入'S'、'R'
}
}
int i;
for(i=0;i<n;i++){//遍历所有进程
while(!cmd[i].empty()){
int x=cmd[i].front().x;
bool f=cmd[i].front().flag;
memset(vis,0,sizeof(vis));
vis[i]=true;
if(unlocked(i,x,f)==false) break;
}
if(!cmd[i].empty()) break;//发生了死锁
}
printf("%d\n",i<n);
}
return 0;
}
优化
把unlocked函数改一下,时间降了5/6。
bool unlocked(int i,int x,bool f){//递归查找可执行的指令
if(vis[x]) return false;
vis[x]=true;
if(!cmd[x].empty()){
int t=cmd[x].front().x;
bool ff=cmd[x].front().flag;
if(t==i){
if(ff==f) return false;//指令不匹配
cmd[i].pop();//找到可执行的指令,弹出
cmd[x].pop();
return true;
}
if(unlocked(x,t,ff)){//执行完了一对指令,从x开始递归查找下一对指令
do{
if(cmd[x].empty()) return true;
memset(vis,0,sizeof(vis));
t=cmd[x].front().x;
ff=cmd[x].front().flag;
vis[x]=true;
}while(unlocked(x,t,ff));
}
}
return false;//没有与之配对的指令
}