UVA

来源:互联网 发布:魅族官方网络授权店 编辑:程序博客网 时间:2024/04/29 11:41
/*题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=745小白书上的说明:本题有一定实际意义,理解题意后编码并不复杂,建议读者一试(然而这题,就是题目不太好完全理解,我最初先看了几次题目,又对照着别人题解上的代码,再看了几次题目,才差不多弄懂了题目意思)*/


/*  法一:  参考了:http://blog.csdn.net/chy20142109/article/details/50756318  //附带说一下,从这个blog里又get到了一些新技能和神操作...虽然原理也就是 #define 的用法而已,但是...这个博主的头文件和 define 的那些模板真的不错~*/

#include <iostream>#include <cstdio>#include <cstring>#define Clean(x, y) memset(x, y, sizeof(x))#define rep(i, j, k) for (int i = j; i <= k; i++)#define Rrep(i, j, k) for (int i = j; i >= k; i--)using namespace std;int np, nt, nf, tp; //nf是指定的步骤数,tp::temp表示一个临时的变量 const int N = 105;int num[N]; //对应每个 place 当前含有 token 的数量int input[N][N], output[N][N];// 每个 transition 对应的输入、输出端// input[i][j] 表示第 i 个 transition 的第 j 个输入端的编号int Inum[N][N];//有可能一个place发出多条路线指向一个transition,记录每个place发出的路线。// Inum[i][j]表示第i个transition的第j个输入端指向第i个transition的路线数 int find (int x, int k){rep(i, 1, input[x][0]) if ( input[x][i] == k) return i;return -1;}//找第 x个 transition 的输入端中有没有值为 k 的,如果有,返回为 k 的输入端,在第 x 个 transition 的所有输入端中的编号;没找到则返回 -1 void init(){Clean(num, 0);Clean(input, 0);Clean(output, 0);Clean(Inum, 0);rep(i, 1, np) scanf("%d", num + i);scanf("%d", &nt);rep(i, 1, nt){while (scanf("%d", &tp), tp){if ( tp < 0 ){int p = find(i, -tp);if ( p != -1 ) Inum[i][p]++;else{input[i][++input[i][0]] = -tp;Inum[i][input[i][0]] = 1;}/* 这里顺带再啰嗦一句,自己想了一段时间的一个细节 因为每次调用 find 函数找不到时,都要先 ++input[i][0] 所以,最后 input[i][0] 会变成 transition 的输入端的总数,如果有输入端输入的 token 数相同时,那就累加到 Inum 数组上,用来记录 "这一种输入端"有几个,其实也还是归类,以便于记录的思想 */ }else output[i][ ++output[i][0] ] = tp;}}scanf("%d", &nf);}bool check (int x){rep(i, 1, input[x][0])if ( num [ input[x][i] ] < Inum[x][i] ) return false;return true;}int main(){int kase = 0;while ( cin >> np && np != 0){init();int step = 0;bool can = true;// 如果存在可变迁的点,则一直变迁,直到达到指定次数 while (can && step < nf){can = false;rep(k, 1, nt){if ( step < nf && check(k) ) // 检查 j 是否可以变迁{can = true;step++;rep(i, 1, input[k][0]) num[ input[k][i] ] -= Inum[k][i];rep(i, 1, output[k][0]) num[ output[k][i] ]++;//每个可以变迁的点,输入和输出端同时变化 } }}printf("Case %d: ",++kase);        if ( step == nf ) printf("still live after %d transitions\n",nf); //到达指定变迁次数       else printf("dead after %d transitions\n",step);  //中途结束        printf("Places with tokens:");         rep(i,1,np)            if (num[i]) printf(" %d (%d)",i,num[i]);        puts("");        puts("");}return 0;}

/*查阅的其他资料整理:http://www.cnblogs.com/woaiheniunai/p/6394672.htmlhttp://blog.csdn.net/wcr1996/article/details/44532065//这种用结构体来处理的方式,写法更简洁,且更容易理解http://blog.csdn.net/c21c21/article/details/44701509//这种用 vector 来处理的方法,也比我模仿重敲的那份代码容易理解一些,而且我觉得这个解法思路的逻辑更加清晰http://blog.csdn.net/weizhuwyzc000/article/details/44100277//这个题解和我贴上的代码的思路比较类似,比较不同的是,它用了map,并且调用了map里的 count 函数,STL的使用,简化了初始化时的代码量*/


原创粉丝点击