CCF-CSP202303C题LDAP【100分】(结构清晰)

非递归写法(栈)

参考了
CCF-CSP认证 202303 500分题解
bitset的基本用法
表达式求值

自认代码结构相对清晰,给卡在这题的同学参考。

#include <bits/stdc++.h>

using namespace std;

const int N = 2510;
typedef bitset<N> STATE;
typedef pair<int, int> PII;

int n, m;
vector<PII> p;
map<PII, STATE> d;
map<int, STATE> S;

stack<STATE> num;
stack<char> op;

void eval(){
	STATE b = num.top(); num.pop();
	STATE a = num.top(); num.pop();
	char c = op.top(); op.pop();
	
	STATE res;
	if (c == '&') res = a & b;
	else res = a | b;
	num.push(res);
}

STATE solve(string str){
	stack<STATE>().swap(num), stack<char>().swap(op);
	for (int i = 0; i < str.size(); i ++ ){
		char c = str[i];
		if (isdigit(c)){
			int x = 0, j = i;
			while (j < str.size() && isdigit(str[j])) x = x * 10 + str[j] - '0', j ++ ;
			char oper = str[j];
			j ++ ;
			int y = 0;
			while (j < str.size() && isdigit(str[j])) y = y * 10 + str[j] - '0', j ++ ;
			i = j - 1;
			
			if (oper == ':') num.push(d[{x, y}]);
			else num.push(~d[{x, y}] & S[x]);
		}
		else if (c == '(') op.push(c);
		else if (c == ')'){
			while (op.top() != '(') eval();
			op.pop();	
		}
		else{
			while (op.size() && op.top() != '(') eval();
			op.push(c);	
		}
	}
	while (op.size()) eval();
	return num.top();
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	cin >> n;
	for (int i = 0; i < n; i ++ ){
		int t;
		cin >> t;
		p.push_back({t, i});
		int cnt;
		cin >> cnt;
		while (cnt -- ){
			int x, y;
			cin >> x >> y;
			d[{x, y}][i] = 1;
			S[x][i] = 1;
		}
	}
	sort(p.begin(), p.end());
	
	cin >> m;	
	while (m -- ){
		string str;
		cin >> str;
		STATE state = solve(str);
		
		vector<int> res;
		for (int i = 0; i < n; i ++ ){
			int x = p[i].first, y = p[i].second;
			if (state[y]) res.push_back(x);
		}
		for (int i = 0; i < res.size(); i ++ ) cout << res[i] << " \n"[i == res.size() - 1];
		if (res.empty()) cout << endl;
	}
		
	return 0;
}

/*
2
1 2 1 2 2 3
2 2 2 3 3 1
4
1:2
3~1
&(1:2)(2:3)
|(1:2)(3:1)
*/

运行时间也还行
运行时间

递归写法

另外,有个很凑巧的递归写法,考场上试出来的。利用了scanf的机制,用%d读字符,会将读取的字符自动退回输入缓冲区,原用于接收的int变量tmp值未改变。
参考C语言使用%d读入字符会发生什么

#include <bits/stdc++.h>

using namespace std;

const int N = 2510;
typedef bitset<N> STATE;
typedef pair<int, int> PII;

int n, m;
vector<PII> p;
map<PII, STATE> d;
map<int, STATE> S;

STATE get(){
    int tmp = 0;
    scanf("%d", &tmp);
    if (tmp){
        int x = tmp, y;
        char op;
        cin >> op >> y;
        if (op == ':') return d[{x, y}];
        else return ~d[{x, y}] & S[x];
    }
    
    char op;
    scanf("%c", &op);
    getchar();
    STATE x = get();
    getchar(); getchar();
    STATE y = get();
    getchar();
    
    if (op == '&') return x & y;
    else return x | y;
}

int main(){
    scanf("%d", &n);
	for (int i = 0; i < n; i ++ ){
		int t;
		scanf("%d", &t);
		p.push_back({t, i});
		int cnt;
		scanf("%d", &cnt);
		while (cnt -- ){
			int x, y;
			scanf("%d %d", &x, &y);
			d[{x, y}][i] = 1;
			S[x][i] = 1;
		}
	}
	sort(p.begin(), p.end());
	
	scanf("%d", &m);
	while (m -- ){
		STATE state = get();
		getchar();
		
		vector<int> res;
		for (int i = 0; i < n; i ++ ){
			int x = p[i].first, y = p[i].second;
			if (state[y]) res.push_back(x);
		}
		for (int i = 0; i < res.size(); i ++ ) printf(" %d" + !i, res[i]);
		puts("");
	}
		
	return 0;
}

/*
2
1 2 1 2 2 3
2 2 2 3 3 1
4
1:2
3~1
&(1:2)(2:3)
|(1:2)(3:1)
*/

时间慢了1s
运行时间
更正常一点的写法

#include <bits/stdc++.h>

using namespace std;

const int N = 2510;
typedef bitset<N> STATE;
typedef pair<int, int> PII;

int n, m;
vector<PII> p;
map<PII, STATE> d;
map<int, STATE> S;

string str;
STATE state;

int get(int u){
    if (isdigit(str[u])){
        int x = 0, y = 0;
        while (u < str.size() && isdigit(str[u])) x = x * 10 + str[u] - '0', u ++ ;
        char op = str[u]; u ++ ;
        while (u < str.size() && isdigit(str[u])) y = y * 10 + str[u] - '0', u ++ ;
        
        if (op == ':') state = d[{x, y}];
        else state = ~d[{x, y}] & S[x];
        return u;
    }
    
    char op = str[u];
    u ++ ;
    u = get(u + 1);
    STATE x = state;
    u ++ ;
    u = get(u + 1);
    STATE y = state;
    
    if (op == '&') state =  x & y;
    else state = x | y;
    
    return u + 1;
}

int main(){
    scanf("%d", &n);
	for (int i = 0; i < n; i ++ ){
		int t;
		scanf("%d", &t);
		p.push_back({t, i});
		int cnt;
		scanf("%d", &cnt);
		while (cnt -- ){
			int x, y;
			scanf("%d %d", &x, &y);
			d[{x, y}][i] = 1;
			S[x][i] = 1;
		}
	}
	sort(p.begin(), p.end());
	
	scanf("%d", &m);
	while (m -- ){
	    cin >> str;
		get(0);
		
		vector<int> res;
		for (int i = 0; i < n; i ++ ){
			int x = p[i].first, y = p[i].second;
			if (state[y]) res.push_back(x);
		}
		for (int i = 0; i < res.size(); i ++ ) printf(" %d" + !i, res[i]);
		puts("");
	}
		
	return 0;
}

/*
2
1 2 1 2 2 3
2 2 2 3 3 1
4
1:2
3~1
&(1:2)(2:3)
|(1:2)(3:1)
*/

可能更好想到的做法,属性值直接存储,每位单独进行判断。不用unorder_map则70分。

#include <bits/stdc++.h>

using namespace std;

const int N = 2510;
typedef pair<int, int> PII;

int n, m;
vector<PII> p;
unordered_map<int, int> v[N];

string str;
bool flag;
int aim;
int get(int u){
    if (isdigit(str[u])){
        int x = 0, y = 0;
        while (u < str.size() && isdigit(str[u])) x = x * 10 + str[u] - '0', u ++ ;
        char op = str[u]; u ++ ;
        while (u < str.size() && isdigit(str[u])) y = y * 10 + str[u] - '0', u ++ ;
        
        if (!v[aim].count(x)) flag = false;
        else if (op == ':' && v[aim][x] == y) flag = true;
        else if (op == '~' && v[aim][x] != y) flag = true;
        else flag = false;
        
        return u;
    }
    
    char op = str[u];
    u ++ ;
    u = get(u + 1);
    bool x = flag;
    u ++ ;
    u = get(u + 1);
    bool y = flag;
    
    if (op == '&') flag = x && y;
    else flag = x || y;
    
    return u + 1;
}

int main(){
    scanf("%d", &n);
	for (int i = 0; i < n; i ++ ){
		int t;
		scanf("%d", &t);
		p.push_back({t, i});
		int cnt;
		scanf("%d", &cnt);
		while (cnt -- ){
			int x, y;
			scanf("%d %d", &x, &y);
			v[i][x] = y;
		}
	}
	sort(p.begin(), p.end());
	
	scanf("%d", &m);
	while (m -- ){
	    cin >> str;
		
		vector<int> res;
		for (int i = 0; i < n; i ++ ){
			int x = p[i].first, y = p[i].second;
			aim = y;
			get(0);
			if (flag) res.push_back(x);
		}
		for (int i = 0; i < res.size(); i ++ ) printf(" %d" + !i, res[i]);
		puts("");
	}
		
	return 0;
}

/*
2
1 2 1 2 2 3
2 2 2 3 3 1
4
1:2
3~1
&(1:2)(2:3)
|(1:2)(3:1)
*/

时间慢了很多
运行时间

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值