算法竞赛入门经典177页,模拟
题目意思:
np个节点 p[1], p[2], … , p[np], 每个节点有若干个牌子 token, 节点与节点之间不直接联系,中间间隔了
一个叫 发射站 trans 的玩意。每一节点向外只能指向一个 发射站。并且,一个节点指向同一个发射站若干次,节点就需要若干个 token 。
发射站也是不能直接相连,
多个节点,可以同时指向一个发射站;
每一个发射站,可能指向若干个 节点。
一个发射站,是否能点火发射,主要看看这个发射站 Trans ,指向 Trans 的每一个节点,节点手中的牌子 token 是否足够。
只有所有的节点的 token 都足够,这个发射站才能点火。
点火之后,指向 发射站 Trans 的所有节点,会减少对应的 token ,而 发射站 Trans 指出的 节点, 这些节点的token 会增加对应的
token. 题目问:进过若干次点火,要么到达循环次数,要么就没有足够的 token 来点火。
此时,每一节点拥有的token数。
本题要点:
1、看懂题目意思,知道样例, 然后暴力模拟。
2、把题目的图画下来,走一下样例就知道了。本质是一道语文题。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int MaxN = 110;
int np, nt, cycle;
int pos[MaxN]; //pos[i]表示第i个 NP 的 token数量
int In[MaxN], Out[MaxN];struct node
{
int id, token;
};struct NT
{
vector<node> in, out;
}trans[MaxN];bool check(int k)
{
int len = trans[k].in.size(), token, id;for(int i = 0; i < len; ++i){
token = trans[k].in[i].token, id = trans[k].in[i].id;if(pos[id] < token)return false;}return true;
}void handle(int k)
{
int len = trans[k].in.size(), token, id;for(int i = 0; i < len; ++i){
token = trans[k].in[i].token, id = trans[k].in[i].id;pos[id] -= token;}len = trans[k].out.size();for(int i = 0; i < len; ++i){
token = trans[k].out[i].token, id = trans[k].out[i].id;pos[id] += token;}
}void solve(int count)
{
printf("Case %d: ", count);int cnt = 0;bool enough = false;while(true){
enough = false;for(int i = 1; i <= nt; ++i){
if(check(i)){
handle(i);enough = true;++cnt;break;}}if(!enough)break;if(cnt >= cycle)break;}if(cnt >= cycle){
printf("still live after %d transitions\n", cycle);}else{
printf("dead after %d transitions\n", cnt);}printf("Places with tokens:");for(int i = 1; i <= np; ++i){
if(pos[i])printf(" %d (%d)", i, pos[i]);}printf("\n\n");
}int main()
{
int id, count = 0;node tmp;while(scanf("%d", &np) != EOF && np){
for(int i = 0; i < MaxN; ++i){
trans[i].in.clear();trans[i].out.clear();}memset(pos, 0, sizeof pos);for(int i = 1; i <= np; ++i){
scanf("%d", &pos[i]);}scanf("%d", &nt);for(int i = 1; i <= nt; ++i){
memset(In, 0, sizeof In);memset(Out, 0, sizeof Out);while(scanf("%d", &id) && id) {
if(id < 0){
In[-id]++; }else{
Out[id]++;}}for(int j = 1; j <= np; ++j){
if(In[j]){
tmp.id = j, tmp.token = In[j]; trans[i].in.push_back(tmp);}if(Out[j]){
tmp.id = j, tmp.token = Out[j];trans[i].out.push_back(tmp);}}}scanf("%d", &cycle);solve(++count);}return 0;
}/* 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 0 *//* Case 1: still live after 100 transitions Places with tokens: 1 (1)Case 2: dead after 9 transitions Places with tokens: 2 (1) */