纯记录一下, 感兴趣的请移步大佬博客
题目来源
http://118.190.20.162/view.page?gpid=T111
大佬博客
层级:https://blog.csdn.net/qq_44528283/article/details/109501132
拓扑排序:https://blog.csdn.net/qq_44528283/article/details/113446330
层级: 根据大佬的代码写得 (0分)(自己没注意细节)
#include <iostream>
#include <string.h>
#include <vector>
#include <map>
#include <algorithm>
#include <sstream>
using namespace std;
struct device {
int id; // 器件编号
string type; // 器件类型
bool ct; // 器件是否构建好了
int level; // 器件层级
int output; // 器件输出
vector<string> input_str;// 器件输入的器件/输入
vector<int> input; // 器件此次的输入
vector<bool> inputDecFlag;// 器件在对应位置上的输入是否构建好了
device (){
level = -1;
ct = false;
}
compute() {
int result = input[0];
if (type == "NOT") {
result = !result;
}
else if (type == "AND") {
for (int i = 1; i < input.size(); ++i) {
result &= input[i];
}
}
else if (type == "OR") {
for (int i = 1; i < input.size(); ++i) {
result |= input[i];
}
}
else if (type == "XOR") {
for (int i = 1; i < input.size(); ++i) {
result ^= input[i];
}
}
else if (type == "NAND") {
for (int i = 1; i < input.size(); ++i) {
result &= input[i];
}
result = !result;
}
else {
for (int i = 1; i < input.size(); ++i) {
result |= input[i];
}
result = !result;
}
output = result;
}
};
int strToNum(string input_str) {
/*
int result = 0;
for (int i = 1; i < input_str.size(); ++i) {
result = result * 10 + (input_str[i] - '0');
}
return result;
*/
int result;
string str = input_str.substr(1); //截取I/O后面的数字字符串
stringstream ss;
ss << str;
ss >> result;
return result;
}
bool cmp(device d1, device d2) {
return d1.level < d2.level; // <
}
int main() {
int Q;
cin>>Q;
for (int q = 0; q < Q; ++q) {
int M, N;
cin>>M>>N;
// 器件
device dce[N+2];
// 输入器件信息
for (int i = 1; i <= N; ++i) {
string FUNC;
int k;
cin>>FUNC>>k;
dce[i].type = FUNC;
dce[i].id = i;
for (int j = 0; j < k; ++j) {
string inInfo;
cin>>inInfo;
dce[i].inputDecFlag.emplace_back(false);
dce[i].input_str.emplace_back(inInfo);
}
}
int S;
cin>>S;
// 输入
//vector<vector<int> > input;
int input[S][M];
//vector<vector<int> > outputDce;
vector<int> outputDce[S];
// 输入每次输入的信息
for (int i = 0; i < S; ++i) {
//input.emplace_back(vector<int>());
for (int j = 0; j < M; ++j) {
int tmp;
cin>>tmp;
//input[i].emplace_back(tmp);
input[i][j] = tmp;
}
}
// 输入每次输出的要求
for (int i = 0; i < S; ++i) {
int num;
cin>>num;
//outputDce.emplace_back(vector<int>());
for (int j = 0; j < num; ++j) {
int tmp;
cin>>tmp;
outputDce[i].emplace_back(tmp);
}
}
//
bool loop = false;
// 构建设备之间的联系
while (1) {
int preState[N + 1];
// 保留前一次的层级
for (int i = 1; i <= N; ++i) {
preState[i] = dce[i].level;
}
// 更新层级
int cont = 0; // 记录是否有更新
for (int i = 1; i <= N; ++i) {
// 当前设备未构建完成
if ( !dce[i].ct) {
++cont;
// 对每个输入设备
for (int j = 0; j < dce[i].input_str.size(); ++j) {
// 当前设备未入册
if ( !dce[i].inputDecFlag[j]) {
string str = dce[i].input_str[j];
int preNum = strToNum(str);
// 直接接输入
if (str[0] == 'I') {
dce[i].inputDecFlag[j] = true;
//dce[preNum].level = max(0, dce[preNum].level);
dce[i].level = max(0, dce[i].level);
}
// 从其他设备接入
else {
// 如果这个设备的输入是另一个设备的输出, 且该设备已经构建好了
if (dce[preNum].ct) {
dce[i].inputDecFlag[j] = true;
//dce[preNum].level = max(dce[preNum].level + 1, dce[preNum].level);
dce[i].level = max(dce[preNum].level + 1, dce[i].level);
}
}
}
}
// 如果当前设备输入都已入册
for (int j = 0; j < dce[i].input_str.size(); ++j) {
if (dce[i].inputDecFlag[j] == false) { // 未全部入册
break;
}
if (j == dce[i].input_str.size() - 1) { // 全入册了
dce[i].ct = true;
}
}
}
}
// 没有更新了, 说明当前没有环路, 且设备间的关系构建完成
if (cont == 0) {
break;
}
// 判断是否有环路
for (int i = 1; i <= N; ++i) {
if (preState[i] != dce[i].level) {
break;
}
if (i == N) {
loop = true;
}
}
// 有环路
if (loop) {
break;
}
}
// 判断是否有环路
if (loop) {
cout<<"LOOP"<<endl;
}
else {
// 没有环路, 对于每一次的输入 和 指定的输出 来说, 需要进行如下操作
sort(dce, dce+N, cmp) ; // !!!很重要!!!, 根据level来排序才能不用每次都考虑当前设备前一个设备的输出啦
for (int i = 0; i < S; ++i) {
map<int, int> id2output;
// 计算
// 对每个设备
for (int j = 1; j <= N; ++j) {
for (int sIndex = 0; sIndex < dce[j].input_str.size(); ++sIndex) {
string str = dce[j].input_str[sIndex];
if (str[0] == 'I') {
dce[j].input.emplace_back(input[i][strToNum(str) - 1]); // - 1
}
else {
dce[j].input.emplace_back(dce[strToNum(str)].output);
}
}
// 计算
dce[j].compute();
id2output[j] = dce[j].output;
}
// 输出
for (int j = 0; j < outputDce[i].size(); ++j) {
cout<<id2output[outputDce[i][j]]<<" ";
}
cout<<endl;
id2output.clear();
for (int j = 1; j <= N; ++j) {
dce[j].input.clear();
}
}
}
}
return 0;
}
层级: 60分, 运行超时, !细节!
照着大佬的代码,改了很多地方。几乎除了变量名外,其他都变了。
我猜主要原因是 sort()那里,我写的是+N, 不是 +N+2。
#include <iostream>
#include <string.h>
#include <vector>
#include <map>
#include <algorithm>
#include <sstream>
using namespace std;
struct device {
int id; // 器件编号
string type; // 器件类型
bool ct; // 器件是否构建好了
int level; // 器件层级
int output; // 器件输出
vector<string> input_str;// 器件输入的器件/输入
vector<int> input; // 器件此次的输入
vector<bool> inputDecFlag;// 器件在对应位置上的输入是否构建好了
device (){
level = -1;
ct = false;
}
compute()
{
int result = input[0];
if(type=="NOT") result=!input[0];
else if(type=="AND")
{
for(int i=1;i<input.size();i++)
{
result &= input[i];
}
}
else if(type=="OR")
{
for(int i=1;i<input.size();i++)
{
result |= input[i];
}
}
else if(type=="XOR")
{
for(int i=1;i<input.size();i++)
{
result ^= input[i];
}
}
else if(type=="NAND")
{
for(int i=1;i<input.size();i++)
{
result &= input[i];
}
result = !result;
}
else
{
for(int i=1;i<input.size();i++)
{
result |= input[i];
}
result = !result;
}
output = result;
}
};
int strToNum(string s) {
int result;
string str = s.substr(1); //截取I/O后面的数字字符串
stringstream ss;
ss << str;
ss >> result;
return result;
}
bool cmp(device d1, device d2) {
return d1.level < d2.level; // <
}
int main() {
int Q;
cin>>Q;
for (int q = 0; q < Q; ++q) {
int M, N;
cin>>M>>N;
// 器件
device dce[N];
// 输入器件信息
for (int i = 0; i < N; ++i) {
string FUNC;
int k;
cin>>FUNC>>k;
dce[i].type = FUNC;
dce[i].id = i +1;
for (int j = 0; j < k; ++j) {
string inInfo;
cin>>inInfo;
dce[i].inputDecFlag.emplace_back(false);
dce[i].input_str.emplace_back(inInfo);
}
}
int S;
cin>>S;
// 输入
//vector<vector<int> > input;
int input[S][M];
//vector<vector<int> > outputDce;
vector<int> outputDce[S];
// 输入每次输入的信息
for (int i = 0; i < S; ++i) {
//input.emplace_back(vector<int>());
for (int j = 0; j < M; ++j) {
//int tmp;
cin>>input[i][j];
//input[i].emplace_back(tmp);
//input[i][j] = tmp;
}
}
// 输入每次输出的要求
for (int i = 0; i < S; ++i) {
int num;
cin>>num;
//outputDce.emplace_back(vector<int>());
for (int j = 0; j < num; ++j) {
int tmp;
cin>>tmp;
outputDce[i].emplace_back(tmp);
}
}
//
bool loop = false;
int cont = 0; // 记录是否有更新
int preState[N + 1];
// 构建设备之间的联系
while (1) {
cont = 0;
// 保留前一次的层级
for (int i = 0; i < N; ++i) {
preState[i] = dce[i].level;
}
// 更新层级
for (int i = 0; i < N; ++i) {
// 当前设备未构建完成
if ( !dce[i].ct) {
++cont;
// 对每个输入设备
for (int j = 0; j < dce[i].input_str.size(); ++j) {
// 当前设备未入册
int run_level;
if ( !dce[i].inputDecFlag[j]) {
string str = dce[i].input_str[j];
int preNum = strToNum(str);
// 直接接输入
if (str[0] == 'I') {
run_level = 0;
dce[i].inputDecFlag[j] = true;
//dce[preNum].level = max(0, dce[preNum].level);
//dce[i].level = max(0, dce[i].level);
}
// 从其他设备接入
else if (str[0] == 'O') {
// 如果这个设备的输入是另一个设备的输出, 且该设备已经构建好了
if (dce[preNum - 1].ct) {
dce[i].inputDecFlag[j] = true;
//dce[preNum].level = max(dce[preNum].level + 1, dce[preNum].level);
//dce[i].level = max(dce[preNum].level + 1, dce[i].level);
run_level = dce[preNum - 1].level + 1;
}
}
if (run_level > dce[i].level) {
dce[i].level = run_level;
}
}
}
// 如果当前设备输入都已入册
for (int j = 0; j < dce[i].inputDecFlag.size(); ++j) {
if ( !dce[i].inputDecFlag[j]) { // 未全部入册
break;
}
if (j == dce[i].input_str.size() - 1) { // 全入册了
dce[i].ct = true;
}
}
}
}
// 没有更新了, 说明当前没有环路, 且设备间的关系构建完成
if (cont == 0) {
break;
}
int same_num = 0;
for (int i = 1; i <= N; ++i) {
if (preState[i] == dce[i].level) {
++same_num;
}
}
// 有环路
if (same_num == N) {
loop = true;
break;
}
}
// 判断是否有环路
if (loop) {
cout<<"LOOP"<<endl;
}
else {
// 没有环路, 对于每一次的输入 和 指定的输出 来说, 需要进行如下操作
sort(dce, dce+N, cmp) ; // !!!很重要!!!, 根据level来排序才能不用每次都考虑当前设备前一个设备的输出啦
for (int i = 0; i < S; ++i) {
map<int, int> id2output;
// 计算
// 对每个设备
for (int j = 0; j < N; ++j) {
for (int sIndex = 0; sIndex < dce[j].input_str.size(); ++sIndex) {
string str = dce[j].input_str[sIndex];
if (str[0] == 'I') {
dce[j].input.emplace_back(input[i][strToNum(str) - 1]); // - 1
}
else {
//dce[j].input.emplace_back(dce[strToNum(str)].output);
dce[j].input.emplace_back(id2output[strToNum(str)]);
}
}
// 计算
dce[j].compute();
id2output[dce[j].id] = dce[j].output;
}
// 输出
for (int j = 0; j < outputDce[i].size(); ++j) {
cout<<id2output[outputDce[i][j]]<<" ";
}
cout<<endl;
id2output.clear();
for (int j = 0; j < N; ++j) {
dce[j].input.clear();
}
}
}
}
return 0;
}
层级:终于100了
改动了一个地方,将i=1->N 改成了 i=0->N-1.
#include <iostream>
#include <string.h>
#include <vector>
#include <map>
#include <algorithm>
#include <sstream>
using namespace std;
struct device {
int id; // 器件编号
string type; // 器件类型
bool ct; // 器件是否构建好了
int level; // 器件层级
int output; // 器件输出
vector<string> input_str;// 器件输入的器件/输入
vector<int> input; // 器件此次的输入
vector<bool> inputDecFlag;// 器件在对应位置上的输入是否构建好了
device (){
level = -1;
ct = false;
}
compute()
{
int result = input[0];
if(type=="NOT") result=!input[0];
else if(type=="AND")
{
for(int i=1;i<input.size();i++)
{
result &= input[i];
}
}
else if(type=="OR")
{
for(int i=1;i<input.size();i++)
{
result |= input[i];
}
}
else if(type=="XOR")
{
for(int i=1;i<input.size();i++)
{
result ^= input[i];
}
}
else if(type=="NAND")
{
for(int i=1;i<input.size();i++)
{
result &= input[i];
}
result = !result;
}
else
{
for(int i=1;i<input.size();i++)
{
result |= input[i];
}
result = !result;
}
output = result;
}
};
int strToNum(string s) {
int result;
string str = s.substr(1); //截取I/O后面的数字字符串
stringstream ss;
ss << str;
ss >> result;
return result;
}
bool cmp(device d1, device d2) {
return d1.level < d2.level; // <
}
int main() {
int Q;
cin>>Q;
for (int q = 0; q < Q; ++q) {
int M, N;
cin>>M>>N;
// 器件
device dce[N];
// 输入器件信息
for (int i = 0; i < N; ++i) {
string FUNC;
int k;
cin>>FUNC>>k;
dce[i].type = FUNC;
dce[i].id = i +1;
for (int j = 0; j < k; ++j) {
string inInfo;
cin>>inInfo;
dce[i].inputDecFlag.emplace_back(false);
dce[i].input_str.emplace_back(inInfo);
}
}
int S;
cin>>S;
// 输入
//vector<vector<int> > input;
int input[S][M];
//vector<vector<int> > outputDce;
vector<int> outputDce[S];
// 输入每次输入的信息
for (int i = 0; i < S; ++i) {
//input.emplace_back(vector<int>());
for (int j = 0; j < M; ++j) {
//int tmp;
cin>>input[i][j];
//input[i].emplace_back(tmp);
//input[i][j] = tmp;
}
}
// 输入每次输出的要求
for (int i = 0; i < S; ++i) {
int num;
cin>>num;
//outputDce.emplace_back(vector<int>());
for (int j = 0; j < num; ++j) {
int tmp;
cin>>tmp;
outputDce[i].emplace_back(tmp);
}
}
//
bool loop = false;
int cont = 0; // 记录是否有更新
int preState[N];
// 构建设备之间的联系
while (1) {
cont = 0;
// 保留前一次的层级
for (int i = 0; i < N; ++i) {
preState[i] = dce[i].level;
}
// 更新层级
for (int i = 0; i < N; ++i) {
// 当前设备未构建完成
if ( !dce[i].ct) {
++cont;
// 对每个输入设备
for (int j = 0; j < dce[i].input_str.size(); ++j) {
// 当前设备未入册
int run_level;
if ( !dce[i].inputDecFlag[j]) {
string str = dce[i].input_str[j];
int preNum = strToNum(str);
// 直接接输入
if (str[0] == 'I') {
run_level = 0;
dce[i].inputDecFlag[j] = true;
//dce[preNum].level = max(0, dce[preNum].level);
//dce[i].level = max(0, dce[i].level);
}
// 从其他设备接入
else if (str[0] == 'O') {
// 如果这个设备的输入是另一个设备的输出, 且该设备已经构建好了
if (dce[preNum - 1].ct) {
dce[i].inputDecFlag[j] = true;
//dce[preNum].level = max(dce[preNum].level + 1, dce[preNum].level);
//dce[i].level = max(dce[preNum].level + 1, dce[i].level);
run_level = dce[preNum - 1].level + 1;
}
}
if (run_level > dce[i].level) {
dce[i].level = run_level;
}
}
}
// 如果当前设备输入都已入册
for (int j = 0; j < dce[i].inputDecFlag.size(); ++j) {
if ( !dce[i].inputDecFlag[j]) { // 未全部入册
break;
}
if (j == dce[i].input_str.size() - 1) { // 全入册了
dce[i].ct = true;
}
}
}
}
// 没有更新了, 说明当前没有环路, 且设备间的关系构建完成
if (cont == 0) {
break;
}
int same_num = 0;
for (int i = 0; i < N; ++i) { /* enmmm,这里 i = 0->N-1 */
if (preState[i] == dce[i].level) {
++same_num;
}
}
// 有环路
if (same_num == N) {
loop = true;
break;
}
}
// 判断是否有环路
if (loop) {
cout<<"LOOP"<<endl;
}
else {
// 没有环路, 对于每一次的输入 和 指定的输出 来说, 需要进行如下操作
sort(dce, dce+N, cmp) ; // !!!很重要!!!, 根据level来排序才能不用每次都考虑当前设备前一个设备的输出啦
for (int i = 0; i < S; ++i) {
map<int, int> id2output;
// 计算
// 对每个设备
for (int j = 0; j < N; ++j) {
for (int sIndex = 0; sIndex < dce[j].input_str.size(); ++sIndex) {
string str = dce[j].input_str[sIndex];
if (str[0] == 'I') {
dce[j].input.emplace_back(input[i][strToNum(str) - 1]); // - 1
}
else {
//dce[j].input.emplace_back(dce[strToNum(str)].output);
dce[j].input.emplace_back(id2output[strToNum(str)]);
}
}
// 计算
dce[j].compute();
id2output[dce[j].id] = dce[j].output;
}
// 输出
for (int j = 0; j < outputDce[i].size(); ++j) {
cout<<id2output[outputDce[i][j]]<<" ";
}
cout<<endl;
id2output.clear();
for (int j = 0; j < N; ++j) {
dce[j].input.clear();
}
}
}
}
return 0;
}
拓扑排序(100)
字符串转数字
#include <iostream>
#include <algorithm>
string s = "A123";
// 需要加(char *), 避免出错。 因为s指向的是常量, 常量不能直接赋值给char*类型。 看解释: https://blog.csdn.net/ku360517703/article/details/8180818
char *cs = (char*)s.substr(1).c_str(); // char *cs = (char*)s.substr(1, s.length() - 1).c_str();
int num_1 = atoi(cs); // 123
int num_2 = atoi(s.substr(1, s.length() - 1).c_str()) ; // 123
虽然看了大佬代码好几遍。但每次自己尝试去写,总会有些疑惑的地方,于是看一遍,重写一遍。第三遍重写终于把完整的代码和思路写完啦,并且一次就写出来了满分~ 不得不说大佬写的博客真的让人受益匪浅。
学到的知识点:
1、图、邻接表的构建。
2、有向无环图的检测与广搜 ————— ! 入度很重要 !。
3、mencpy()、memset()、fill、atoi() 的使用
自己再随意记录记录:
1、 注意全局定义时的MAXN 和 MAXM的使用
2、弄清楚tab的含义, tab[i][j]是 i 指向 j, 那 i 就有可能是 输入、也可能是器件, j 只可能是器件。
3、注意各下标的含义, 注意有没有包含输入。 同时,最好是在输入或者说初始化就给弄好,不要搞到要计算结果的时候再去+1、-1的,这样很容易弄混淆、弄糊涂。
4、全局变量要记得清理清理, clear clear。
5、多多练题, 加油~
贴上代码:
#include <iostream>
#include <vector>
#include <queue> // queue
#include <string.h> // memcpy ...
#include <algorithm> // atoi、 fill
using namespace std;
// 常量
const int MAXK = 5;
const int MAXN = 501;
const int MAXM = 2501; // k * N
const int MAXS = 100001;
// 器件
vector<int> tab[MAXN + MAXM]; // 邻接表(包含输入和器件) dce[i][j]: i->j
string type[MAXN]; // 每个器件的类型
int InD[MAXN + MAXM]; // 每个器件和输入的入度
// 输入
vector<vector<int> > input; // 输入
vector<vector<int> > outputDev; // 每个输入要求输出的器件编号
// 输出
int output[MAXN + MAXM]; // 输入和器件的结果
// 判断邻接表是不是有向无环图
bool topologicalSort(int N, int M) {
int curInD[MAXN + MAXM];
memcpy(curInD, InD, sizeof(InD));
queue<int> que; // 记录入度为0
for (int i = 0; i < N + M; ++i) {
if (curInD[i] == 0) {
que.push(i);
}
}
int num = 0;
while ( !que.empty()) {
int cur = que.front();
que.pop();
++num;
for (int i = 0; i < tab[cur].size(); ++i) {
int nex = tab[cur][i];
if (curInD[nex] != 0) {
--curInD[nex];
if (curInD[nex] == 0) {
que.push(nex);
}
}
}
}
if (num == N + M) {
return false;
}
else {
return true;
}
}
void compute(int N, int M) {
bool ini[MAXN] = {false};
int curInD[MAXN + MAXM];
memcpy(curInD, InD, sizeof(InD));
queue<int> que; // 记录入度为0
for (int i = 0; i < N + M; ++i) {
if (curInD[i] == 0) {
que.push(i);
}
}
while ( !que.empty()) {
int cur = que.front();
que.pop();
for (int i = 0; i < tab[cur].size(); ++i) {
int nex = tab[cur][i];
if (curInD[nex] != 0) {
--curInD[nex];
// 器件未被初始化过, 没遇到过输入
if (ini[nex - M] == false) {
output[nex] = output[cur];
ini[nex - M] = true;
if (type[nex - M] == "NOT") {
output[nex] = !output[nex];
}
}
// 遇见过输入
else {
if (type[nex - M] == "AND" || type[nex - M] == "NAND") {
output[nex] = output[nex] & output[cur];
}
else if (type[nex - M] == "OR" || type[nex - M] == "NOR") {
output[nex] = output[nex] | output[cur];
}
else if (type[nex - M] == "XOR") {
output[nex] = output[nex] ^ output[cur];
}
}
if (curInD[nex] == 0) {
que.push(nex);
if (type[nex - M] == "NOR" || type[nex - M] == "NAND") {
output[nex] = !output[nex];
}
}
}
}
}
}
int main() {
int Q;
cin>>Q;
for (int q = 0; q < Q; ++q) {
int M, N;
cin>>M>>N;
fill(InD, InD + MAXM + MAXN, 0); // 初始化入度 // 清理
// 输入器件信息, 构建邻接表
for (int n = 0; n < N; ++n) {
cin>>type[n];
int K; // 每个器件的输入数
cin>>K;
InD[n + M] = K; // 记录器件入度数
for (int k = 0; k < K; ++k) {
string t;
cin>>t;
int pre = atoi(t.substr(1).c_str()) - 1; // -1, start from 0
if (t[0] == 'O') { // 器件编号 (-1+m)
pre += M;
}
tab[pre].emplace_back(n + M); // 构建邻接表
}
}
// S个输入
int S;
cin>>S;
// S个输入的输入
for (int s = 0; s < S; ++s) {
input.emplace_back();
for (int m = 0; m < M; ++m) {
int cur;
cin>>cur;
input[s].emplace_back(cur);
}
}
// S个输入对应要求输出的器件的编号
for (int s = 0; s < S; ++s) {
outputDev.emplace_back();
int num;
cin>>num;
for (int n = 0; n < num; ++n) {
int cur;
cin>>cur;
cur += (M - 1);
outputDev[s].emplace_back(cur);
}
}
// 成环
if (topologicalSort(N, M)) {
cout<<"LOOP"<<endl;
}
// 不成环
else {
for (int s = 0; s < S; ++s) {
// 初始化
fill(output, output + MAXN + MAXM, 0); // 清理
for (int i = 0; i < M; ++i) {
output[i] = input[s][i];
}
compute(N, M);
// 输出
for (int i = 0; i < outputDev[s].size(); ++i) {
cout<<output[outputDev[s][i]]<<" ";
}
cout<<endl;
}
}
// 清理一下
input.clear();
outputDev.clear();
for (int i = 0; i < MAXN + MAXM; i++) {
tab[i].clear();
}
/*
for (int i = 0; i < MAXN; ++i) {
type[i] = "";
}
*/
}
return 0;
}