CSP认证(2022-06-12)

2 篇文章 0 订阅
博主分享了自己参与编程竞赛的经历,详细分析了在归一化处理、图遍历和角色授权问题上的解题思路及错误。在归一化处理中,博主正确实现了计算并归一化数组的方法。在寻宝问题上,由于一开始使用vector导致超时,后来改为map顺利解决。角色授权题目上,博主的解决方案存在效率问题,未能通过所有测试用例,认识到优化判断逻辑的重要性。
摘要由CSDN通过智能技术生成

个人感想:
做了四个小时写了270分也不知道怎么讲,目标是300所以多少有些失望(大佬轻点喷谢谢QAQ),作为一个菜鸡四五百分肯定是不奢求,但是300都没有多少有些可惜。
第一题大概花了十分钟左右,速度也不算快,看懂题目以后就跟着敲就行了。
第二题有些急了,处理图的时候把存图的容器map写成了vector,白白浪费一个钟,后面也才注意到用vector存储的话有边界限制1e9显然不够,换成map以后马上从40分变成100分了。
第三题,一个又臭又长的模拟,最后也只是写出了70分,在优化方面显然不是那么擅长,判断那里n * m的for循环乘上q肯定回TL,看了一下大佬的代码在判断上是(n+m)的而我是n * m,差距一眼就出来了。
只能说自己还不够强,还不够努力把。

一.归一化处理

在这里插入图片描述在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
double num,a[1005],avg,fc,n;
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)cin>>a[i],avg+=a[i];
	avg=avg*1.0/n;
	for(int i=0;i<n;i++)fc+=pow(a[i]-avg,2);
	fc=fc*1.0/n;
	for(int i=0;i<n;i++)printf("%lf\n",(a[i]-avg)/pow(fc,0.5));
	return 0;
} 

二.寻宝!大冒险!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int MAX=1005;
map<int,map<int,int> >mp;//vector只能过40%
struct node{
	int x,y;
}point[MAX];
int graph[55][55];
int main()
{
	int n,L,S;
	cin>>n>>L>>S;
	for(int i=0;i<n;i++){
		cin>>point[i].x>>point[i].y;
		mp[point[i].x][point[i].y]=1;
	}
	for(int i=S;i>=0;i--)//此处注意从后往前输入
		for(int j=0;j<=S;j++)
			cin>>graph[i][j];
	int ans=0;
	for(int k=0;k<n;k++)
	{
		bool flag=true;
		int x=point[k].x,y=point[k].y;
		for(int i=0;i<=S;i++)
		{
			for(int j=0;j<=S;j++)
			{
				if(x+i>L||y+j>L||graph[i][j]!=mp[x+i][y+j])
				{
					flag=false;
					break;
				}
			}
			if(!flag)break;
		}
		if(flag)ans++;
	}
	cout<<ans<<endl;
	return 0;
}

三.角色授权

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解题思路:大模拟,不过只能拿70分,最后30TL了,末尾有一个100分的大佬的代码。

//70分代码
#include<bits/stdc++.h>
using namespace std;
int n,m,q;
string s,t="*";
struct node{ 
	string name;
	map<string,int>nvs,nos,nns;
	int nv,no,nn;
}user[505];//用户
struct node2{
	string name;
	map<string,int>nss;
	int ns;
}con[505];//关联 
struct node3{
	string name,che,cat,res;
	map<int,string>ngs;
	int ng;
}opr[5050];//操作 
bool check2(node3 it,string name)//判断关联到的管理员的操作 
{
	for(int i=0;i<n;i++)
		if(user[i].name==name)
			if(user[i].nvs[it.che]||user[i].nvs[t])
				if(user[i].nos[it.cat]||user[i].nos[t])
					if(user[i].nns[it.res]||user[i].nn==0)
						return true;
	return false;
}
bool check(node3 it)//判断关联 
{
	for(int i=0;i<m;i++)
	{
		if(con[i].nss[it.name])//通过名字关联 
			if(check2(it,con[i].name))return true;
		for(int j=0;j<it.ng;j++)//通过用户组关联 
			if(con[i].nss[it.ngs[j]])
				if(check2(it,con[i].name))return true;
	}
	return false;
}
int main()
{
	cin>>n>>m>>q;
	for(int i=0;i<n;i++)//管理员用户 
	{
		cin>>user[i].name>>user[i].nv;
		for(int j=0;j<user[i].nv;j++){cin>>s;user[i].nvs[s]=1;}
		cin>>user[i].no;
		for(int j=0;j<user[i].no;j++){cin>>s;user[i].nos[s]=1;}
		cin>>user[i].nn;
		for(int j=0;j<user[i].nn;j++){cin>>s;user[i].nns[s]=1;}
	}
	for(int i=0;i<m;i++)//关联 
	{
		cin>>con[i].name>>con[i].ns;
		for(int j=0;j<2*con[i].ns;j++){cin>>s;con[i].nss[s]=1;}
	}
	for(int i=0;i<q;i++)//正常用户操作 
	{
		cin>>opr[i].name>>opr[i].ng;
		for(int j=0;j<opr[i].ng;j++)cin>>opr[i].ngs[j];
		cin>>opr[i].che>>opr[i].cat>>opr[i].res;
		if(check(opr[i]))cout<<"1"<<endl;
		else cout<<"0"<<endl;
	}
	return 0;
} 

大佬的代码在初始化数据那些部分相同,主要区别就是判断部分我用了双重for循环,这边显然不是。

//100分
#include <bits/stdc++.h>
using namespace std;

class role
{
public:
    set<string> opl; 
    set<string> opt; 
    set<string> opn; 
};

class group
{
public:
    set<string> rol; 
};

map<string, role> mpr;  
map<string, group> mpg; 

class user
{
public:
    set<string> rol; 
    set<string> grp; 

    bool authchk(string opl, string opt, string opn) 
    {
        for (auto it : rol) 
            if (mpr[it].opl.count("*") || mpr[it].opl.count(opl))
                if (mpr[it].opt.count("*") || mpr[it].opt.count(opt))
                    if (mpr[it].opn.empty() || mpr[it].opn.count(opn))
                        return true;
        for (auto it : grp) 
            if (mpg.count(it))
                for (auto it2 : mpg[it].rol)
                    if (mpr[it2].opl.count("*") || mpr[it2].opl.count(opl))
                        if (mpr[it2].opt.count("*") || mpr[it2].opt.count(opt))
                            if (mpr[it2].opn.empty() || mpr[it2].opn.count(opn))
                                return true;
        return false;
    }
};
map<string, user> mpu; 
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n, m, q, nv, no, nn, k;
    string name, rname, uname, x, y, z, ch;
    cin >> n >> m >> q;
    for (int i = 0; i < n; i++)
    {
        cin >> name >> nv;
        while (nv--)
            cin >> x, mpr[name].opl.emplace(x);
        cin >> no;
        while (no--)
            cin >> x, mpr[name].opt.emplace(x);
        cin >> nn;
        while (nn--)
            cin >> x, mpr[name].opn.emplace(x);
    }

    for (int i = 0; i < m; i++)
    {
        cin >> rname >> k;
        for (int j = 0; j < k; j++)
        {
            cin >> ch >> name;
            if (ch == "g")
                mpg[name].rol.emplace(rname);
            else
                mpu[name].rol.emplace(rname);
        }
    }

    for (int i = 0; i < q; i++)
    {
        cin >> uname >> k;
        for (int j = 0; j < k; j++)
            cin >> name, mpu[uname].grp.emplace(name);
        cin >> x >> y >> z;
        cout << mpu[uname].authchk(x, y, z) << endl;
        mpu[uname].grp.clear();
    }
}
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值