csp 201612-3题目回顾总结

题目链接

http://118.190.20.162/view.page?gpid=T50

解题思路

本题题目较长,但总体来说理解题意后处理方法并不复杂。主要难点有对权限字符串的处理以及对用户、角色、权限之间的嵌套包含关系的表示和最后的查询部分。
本题首先需要用三个结构体来储存用户、角色、和权限。代码如下:

struct cate{
	string name;
	int level;
};

struct role{
	string name;
	struct cate privilege[11];
	int cnum;
};

struct user{
	string name;
	struct role player[11];
	int rnum;
};

struct cate c[105];
struct role r[105];
struct user u[105];

除此之外,对于输入的权限,需要转化成对应结构体的表达形式。相应函数代码如下:

struct cate makecate(string na)
{
	struct cate p;
	if(na.find(":",0) != -1)  //分级类权限 
	{
		int pos = na.find(":",0);
		p.name = na.substr(0,pos);
		p.level = na.at(na.length()-1)-'0';
	}
	else  //不分级类权限 
	{
		p.name = na;
		p.level = -1;
	}
	return p;
}

之后有相应根据名称查找权限、角色和用户的函数之后便可以进入程序的主体部分。主体部分主要包括了输入部分与查找部分。具体主函数代码如下:

int main()
{
	string temp;
	int n1,n2,n3,n4;
	cin >> n1;
	for(int i = 0; i < n1; i++)  //输入权限 
	{
		cin >> temp;
		c[i] = makecate(temp);
	}
	cin >> n2;
	for(int i = 0; i < n2; i++)  //输入角色及包含权限 
	{
		cin >> r[i].name;
		cin >> r[i].cnum;
		for(int j = 0; j < r[i].cnum; j++)
		{
			cin >> temp;
			r[i].privilege[j] = makecate(temp);
		}
	}
	cin >> n3;
	for(int i = 0; i < n3; i++)  //输入用户及包含角色 
	{
		cin >> u[i].name;
		cin >> u[i].rnum;
		for(int j = 0; j < u[i].rnum; j++)
		{
			cin >> temp;
			u[i].player[j] = r[getrole(temp)];
		}
	}
	cin >> n4;
	for(int i = 0; i < n4; i++)  //查找部分 
	{
		int flag = 0,maxlevel = -1;
		string temp1,temp2;
		cin >> temp1 >> temp2;
		int num = getuser(temp1);  //找到对应用户 
		if(num != -1)  //用户存在才能查找权限 
		{
			for(int j = 0; j < u[num].rnum; j++)  //遍历用户角色 
			{
				for(int k = 0; k < u[num].player[j].cnum; k++)  //遍历角色权限 
				{
					struct cate p = makecate(temp2);  //查找时输入的权限 
					if(p.name == u[num].player[j].privilege[k].name)  //该用户包含对应权限,进一步检查权限是否正确 
					{
						if(p.level == -1 && u[num].player[j].privilege[k].level == -1)  //输入权限与用户权限均无级别 
						{
							flag = 1;  //不存在最大权限级别 
						}
						else if(p.level == -1 && u[num].player[j].privilege[k].level != -1)  //输入权限无级别,用户权限有级别 
						{
							flag= 1;
							maxlevel = max(maxlevel,u[num].player[j].privilege[k].level);   //更新权限级别取最大值 
						}
						else if(p.level != -1 && u[num].player[j].privilege[k].level != -1)  // 输入权限和用户权限均有级别 
						{
							if(p.level <= u[num].player[j].privilege[k].level)  //如果输入权限级别小于用户权限级别,权限查找成立 
							{
								flag = 1;
							}
						}
					}
				}
			}
		}
		if(flag == 1 && maxlevel != -1)
		{
			cout << maxlevel << endl;
		}
		else if(flag == 1 && maxlevel == -1)
		{
			cout << "true" << endl;
		}
		else if(flag == 0)
		{
			cout << "false" << endl;
		}
	}
    return 0;
}

综上所述,本题需要注意多处细节,尤其是权限级别部分。首先检查用户是否拥有对应权限,之后再确认权限级别是否存在矛盾,无矛盾才能得出“true”的结果。另外还需注意,只有当输入权限不包含级别时,才要求输出最大权限级别,其他情况只需判断是否具有权限即可。整体代码如下:

#include <iostream> 
#include <cstdio> 
#include <fstream> 
#include <algorithm> 
#include <cmath> 
#include <deque> 
#include <vector> 
#include <queue> 
#include <string> 
#include <cstring> 
#include <map> 
#include <stack> 
#include <set> 
#include<cstdlib>
#include<ctime>
#include<iomanip>
#define ll long long
#define FOR(i,a,n) for(register int i=a;i<n;i++)
#define RF(i,a,n) for(register int i=a;i>n;i--)
#define NIL -1

using namespace std;

struct cate{
	string name;
	int level;
};

struct role{
	string name;
	struct cate privilege[11];
	int cnum;
};

struct user{
	string name;
	struct role player[11];
	int rnum;
};

struct cate c[105];
struct role r[105];
struct user u[105];

int getuser(string na)  //由名称查找对应用户下标 
{
	for(int i = 0; i < 100; i++)
	{
		if(na == u[i].name)
		{
			return i;
		}
	}
	return -1;
}

int getrole(string na)  //由名称查找对应角色下标 
{
	for(int i = 0; i < 100; i++)
	{
		if(na == r[i].name)
		{
			return i;
		}
	}
	return -1;
}

struct cate makecate(string na)
{
	struct cate p;
	if(na.find(":",0) != -1)  //分级类权限 
	{
		int pos = na.find(":",0);
		p.name = na.substr(0,pos);
		p.level = na.at(na.length()-1)-'0';
	}
	else  //不分级类权限 
	{
		p.name = na;
		p.level = -1;
	}
	return p;
}

int getcate(string name)  //由名称查找对应权限下标 
{
	for(int i = 0; i < 100; i++)
	{
		if(name == c[i].name)
		{
			return i;
		}
	}
	return -1;
}

int main()
{
	string temp;
	int n1,n2,n3,n4;
	cin >> n1;
	for(int i = 0; i < n1; i++)  //输入权限 
	{
		cin >> temp;
		c[i] = makecate(temp);
	}
	cin >> n2;
	for(int i = 0; i < n2; i++)  //输入角色及包含权限 
	{
		cin >> r[i].name;
		cin >> r[i].cnum;
		for(int j = 0; j < r[i].cnum; j++)
		{
			cin >> temp;
			r[i].privilege[j] = makecate(temp);
		}
	}
	cin >> n3;
	for(int i = 0; i < n3; i++)  //输入用户及包含角色 
	{
		cin >> u[i].name;
		cin >> u[i].rnum;
		for(int j = 0; j < u[i].rnum; j++)
		{
			cin >> temp;
			u[i].player[j] = r[getrole(temp)];
		}
	}
	cin >> n4;
	for(int i = 0; i < n4; i++)  //查找部分 
	{
		int flag = 0,maxlevel = -1;
		string temp1,temp2;
		cin >> temp1 >> temp2;
		int num = getuser(temp1);  //找到对应用户 
		if(num != -1)  //用户存在才能查找权限 
		{
			for(int j = 0; j < u[num].rnum; j++)  //遍历用户角色 
			{
				for(int k = 0; k < u[num].player[j].cnum; k++)  //遍历角色权限 
				{
					struct cate p = makecate(temp2);  //查找时输入的权限 
					if(p.name == u[num].player[j].privilege[k].name)  //该用户包含对应权限,进一步检查权限是否正确 
					{
						if(p.level == -1 && u[num].player[j].privilege[k].level == -1)  //输入权限与用户权限均无级别 
						{
							flag = 1;  //不存在最大权限级别 
						}
						else if(p.level == -1 && u[num].player[j].privilege[k].level != -1)  //输入权限无级别,用户权限有级别 
						{
							flag= 1;
							maxlevel = max(maxlevel,u[num].player[j].privilege[k].level);   //更新权限级别取最大值 
						}
						else if(p.level != -1 && u[num].player[j].privilege[k].level != -1)  // 输入权限和用户权限均有级别 
						{
							if(p.level <= u[num].player[j].privilege[k].level)  //如果输入权限级别小于用户权限级别,权限查找成立 
							{
								flag = 1;
							}
						}
					}
				}
			}
		}
		if(flag == 1 && maxlevel != -1)
		{
			cout << maxlevel << endl;
		}
		else if(flag == 1 && maxlevel == -1)
		{
			cout << "true" << endl;
		}
		else if(flag == 0)
		{
			cout << "false" << endl;
		}
	}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值