UVa804 习题 6-7 Petri网模拟(Petri Net Simulation,ACM/ICPC World Finals 1998)

原题链接: UVa-804

题目大意:

 模拟Petri网,(图参考原题或紫书)包含NP个库(圆圈),NT个变迁(大棒♂),大棒与若干个input(圆圈)和若干个output(圆圈)相连,只有每个input(也可当做指向大棒的箭头)都有一个小黑球时,input减少一个小黑球,才能完成变迁,然后output里会增加小黑球。题目要求能不能完成给定的跃迁数。

解题思路:

 其实这道题啊我已开始没有看明白的,紫书和原题上都没看懂,后来参考了别的小伙伴的博客才明白。大致主要代码的大致思路就是:依次对每个T(i)进行执行,如果每个input都能执行成功(NP中有token)则执行,则执行output,并将执行T(i)的次数++,否则恢复刚才所有执行的input。一轮(将所有T(i)执行一遍)中任意一个T(i)执行就可以执行下一轮。如果一轮中没有任何一个T(i)执行成功则说明执行失败,返回执行次数。

代码:

#include
#include
#include

using namespace std;

int deal();

const int MAXN = 100 + 10;

int NP[MAXN];			//P(i)现存小球的数量
int NT_in[MAXN][MAXN];		//存储T(i)的input
int NT_out[MAXN][MAXN];		//存储T(i)的output
int n, m, num;

int main()
{
	int kase = 0;
	while (cin >> n && n)
	{
		//初始化
		memset(NT_in,0,sizeof(NT_in));
		memset(NT_out, 0, sizeof(NT_out));
		int k,i, j, x, do_num;
		for (i = 1; i <= n; i++) cin >> NP[i];
		cin >> m;
		for (i = 0; i < m; i++){
			k = j = 0;
			while (cin >> x && x){
				if (x < 0) NT_in[i][j++] = x;
				else NT_out[i][k++] = x;
			}
		}
		cin >> num;
		//处理
		do_num = deal(); //处理函数,返回执行变迁的次数
		//输出
		if(do_num == num) cout << "Case " << ++kase << ": still live after " << do_num << " transitions\n";
		else cout << "Case " << ++kase << ": dead after " << do_num << " transitions\n";
		cout << "Places with tokens:";
		for (int i = 1; i <= n; i++)		//逐个输出有token的P,和个数
			if (NP[i] > 0)	cout << " " << i << " (" << NP[i] << ")";
		cout << endl << endl;
	}
	return 0;
}
/*依次对每个T(i)进行执行,如果每个input都能执行成功(NP中有token)则执行,
则执行output,并将执行T(i)的次数++,否则恢复刚才所有执行的input。
一轮(将所有T(i)执行一遍)中任意一个T(i)执行就可以执行下一轮。
如果一轮中没有任何一个T(i)执行成功则说明执行失败,返回执行次数。*/
int deal()		
{
	int i, j, n = 1;
	while(1)
	{
		bool had_do = false; //该轮中有T(i)执行,可以执行下一轮
		for (i = 0; i < m; i++){
			j = 0; bool can_do = true;//该T(i)执行是否成功
			while (NT_in[i][j] != 0){
				if (NP[-NT_in[i][j]] > 0)	//执行input
					NP[-NT_in[i][j++]]--;		
				else{                    //input执行失败,恢复input之前状态,并将can_do置为false
				
					while (j--)
						NP[-NT_in[i][j]]++;
					can_do = false; break;
				}
			}
			if (can_do)	{				//input执行成功的情况下执行output
				j = 0; n++;//***
				while (NT_out[i][j] != 0){
					NP[NT_out[i][j]]++;
					j++;
				}
				had_do = true;
				if (n > num) return num;
			}
			else break;
		}
		if (!had_do) return n-1;
	}
}


你可能感兴趣的:(ACM,数据结构)