UVa 804 Petri Net Simulation


  Petri Net Simulation 

Input: petri.in A Petri net is a computational model used to illustrate concurrent activity. Each Petri net contains some number of places (represented by circles), transitions (represented by black rectangles), and directed edges used to connect places to transitions, and transitions to places. Each place can hold zero or more tokens (represented by black dots). Here are two examples:

\epsfbox{p804.eps}

In the first Petri net above, there are two places (P1 and P2) and two transitions (T1 and T2). P1 initially has one token; P2 has none. P1 is an input place for transition T1, and P2 is an output place for T1. In the second example there are three places and three transitions, with three tokens in P1. T2 has two input places, both of which are P2.

Operation of a Petri Net 

Each transition in a Petri net is either enabled or disabled. A transition is enabled if there is at least one token in each of its input places. Any transition can fire whenever it is enabled. If multiple transitions are enabled, any one of them may fire. When a transition fires, one token is removed from each of the input places, and one token is added to each of the output places; this is effectively done atomically, as one action. When there are no enabled transitions, a Petri net is said to be dead.

In the top example only T1 is enabled. When it fires one token is removed from P1, and one token is added to P2. Then T2 is enabled. When it fires one token is removed from P2, and one token is added to P1. Clearly this Petri net will repeat this cycle forever.

The bottom example is more interesting. T1 is enabled and fires, effectively moving a token to P2. At this point T1 is still the only enabled transition (T2 requires that P2 have two tokens before it is enabled). T1 fires again, leaving one token in P1 and two tokens in P2. Now both T1 and T2 are enabled. Assume T2 fires, removing two tokens from P2 and adding one token to P3. Now T1 and T3 are enabled. Continuing until no more transitions are enabled, you should see that only one token will be left in P2 after 9 transition firings. (Note that if T1 had fired instead of T2 when both were enabled, this result would have been the same after 9 firings.)

In this problem you will be presented with descriptions of one or more Petri nets. For each you are to simulate some specified number of transition firings, NF, and then report the number of tokens remaining in the places. If the net becomes dead before NF transition firings, you are to report that fact as well.

Input 

Each Petri net description will first contain an integer  NP  (   0 < NP < 100 ) followed by  NP  integers specifying the number of tokens initially in each of the places numbered  1, 2,..., NP . Next there will appear an integer  NT  (   0 < NT < 100 ) specifying the number of transitions. Then, for each transition (in increasing numerical order  1, 2,..., NT ) there will appear a list of integers terminated by zero.

The negative numbers in the list will represent the input places, so the number n indicates there is an input place at n. The positive numbers in the list will indicate the output places, so the number p indicates an output place at p. There will be at least one input place and at least one output place for each transition. Finally, after the description of all NT transitions, there will appear an integer indicating the maximum number of firings you are to simulate, NF. The input will contain one or more Petri net descriptions followed by a zero.

Output 

For each Petri net description in the input display three lines of output. On the first line indicate the number of the input case (numbered sequentially starting with 1) and whether or not  NF  transitions were able to fire. If so, indicate the net is still live after  NF  firings. Otherwise indicate the net is dead, and the number of firings which were completed. In either case, on the second line give the identities of the places which contain one or more tokens after the simulation, and the number of tokens each such place contains. This list should be in ascending order. The third line of output for each set should be blank.

The input data will be selected to guarantee the uniqueness of the correct output displays.

Sample Input 

2
1 0
2
-1 2 0
-2 1 0
100
3
3 0 0
3
-1 2 0
-2 -2 3 0
-3 1 0
100
3
1 0 0
3
-1 2 3 0
-2 1 0
-3 1 0
1
0

Sample Output 

Case 1: still live after 100 transitions
Places with tokens: 1 (1)

Case 2: dead after 9 transitions
Places with tokens: 2 (1)

Case 3: still live after 1 transitions
Places with tokens: 2 (1) 3 (1)



Miguel Revilla 2004-09-17


#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
// place[i]代表第i个place的token数目
int place[200];

// tran_input/output[i]代表第i个transition的place列表
vector<int> tran_input[200];
vector<int> tran_output[200];

int place_num, tran_num, simul_num;

int main()
{
	int g_count = 1;
	// 读入各个情况
	while(scanf("%d", &place_num) && place_num != 0)
	{
		memset(place, 0, sizeof(place));

		for(int i = 1; i <= place_num; i++)
			scanf("%d", &place[i]);

		scanf("%d", &tran_num);
		for(int i = 1; i <= tran_num; i++)
		{
			tran_input[i] = vector<int>();
			tran_output[i] = vector<int>();
			int x;
			while(scanf("%d", &x) && x != 0)
			{
				if(x < 0)
					tran_input[i].push_back(-x);
				else
					tran_output[i].push_back(x);	
			}
		}	
		
		scanf("%d", &simul_num);
		printf("Case %d: ", g_count);
		g_count++;
		// 进行模拟
		int count;
		for(count = 1; count <= simul_num; count++)
		{
			int tran_i;
			// 找到可以enable的transition
			for(tran_i = 1; tran_i <= tran_num; tran_i++)
			{
				int j;
				int enable_flag = 1;
				for(j = 0; j < tran_input[tran_i].size(); j++)
				{
					place[tran_input[tran_i][j]]--;
					if(place[tran_input[tran_i][j]] < 0)
					{
						enable_flag = 0;
					}
				}	

				if(enable_flag == 0)
				{
					for(j = 0; j < tran_input[tran_i].size(); j++)
                                	{       
                                        	place[tran_input[tran_i][j]]++;
                                	}
				}	
				else
				{
					for(j = 0; j < tran_output[tran_i].size(); j++)
                                        {
                                                place[tran_output[tran_i][j]]++;
                                        }
					break;
				}	
			}
			if(tran_i == tran_num + 1)
			{
				printf("dead after %d transitions\n", count-1);
				break;
			}		
		}	
		if(count == simul_num+1)
			printf("still live after %d transitions\n", simul_num);
		printf("Places with tokens:");
		for(int i = 1; i <= place_num; i++)
		{
			if(place[i] > 0)
				printf(" %d (%d)", i, place[i]);
		}	
		printf("\n\n");
	}	
	return 0;	
}

这道题是好题。
这道题我一开始用了一种很复杂的方法做:用结构体建立了place和transition节点,构造了整个图。
然后用队列存储可以enable的节点,进行enable时还要更改检查各个有关的place节点。结果TLE.

想了好久没有方法,后来在网上看了别人的代码。发现只需要存储每个place的token,和每个transition的
输入节点和输出节点就可以了。其实place指向哪个transition的信息并不需要保存。感觉很巧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值