算法竞赛入门经典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)
*/