CSP历年部分真题解答

注:收录的都是我觉得有价值的题目,简单的一般不收录

202212-2 训练计划 

题目链接:训练计划

题解:

这是一道动态规划题,计算最早时间很简单,只需要前一个的最早时间加上训练所需时间即可;

其实对于最晚开始时间也是一样的思路,当前结点最晚开始时间由依赖该结点的所有结点的最晚开始时间决定,所以要从后往前遍历,并且需要一个二维数组记录每个结点的“前驱”,具体看代码实现: 

#include<iostream>
#include<vector>

using namespace::std;

int main(){
    int n,m;//n表示天数,m表示项目数
    cin>>n>>m;
    int *depend=new int[m+1]();//依赖数组
    vector<vector<int>> depended(m+1);//被依赖数组,是一对多关系
    int *time=new int[m+1]();//花费时间数组
    for(int i=1;i<=m;i++){
        cin>>depend[i];
        depended[depend[i]].push_back(i);
    }

    for(int i=1;i<=m;i++)
        cin>>time[i];
    int *earlyStart=new int[m+1]();//最早开始时间
    int *lastStart=new int[m+1]();//最晚开始时间
    //先计算最早开始时间
    earlyStart[1]=1;
    for(int i=2;i<=m;i++){
        if(depend[i]!=0)
            earlyStart[i]=earlyStart[depend[i]]+time[depend[i]];
        else
            earlyStart[i]=1;//没有依赖,可以从第一天开始
    }
    bool canDo=true;//是否能在n天内完成
    for(int i=1;i<=m;i++)
        if(earlyStart[i]+time[i]-1>n){
            canDo=false;
            break;
        }
    for(int i=1;i<=m;i++)
        cout<<earlyStart[i]<<" ";
    cout<<endl;
    if(canDo){
        //计算最晚开始时间,也就是从后往前计算
        for(int i=m;i>=1;i--){
            if(depended[i].empty()){
                lastStart[i]=n+1-time[i];
            }
            else{
                lastStart[i]=lastStart[depended[i][0]]-time[i];
                for(int j=1;j<depended[i].size();j++){
                    lastStart[i]=min(lastStart[i],lastStart[depended[i][j]]-time[i]);//注意,应该是取最小值
                }
            }
        }
        for(int i=1;i<=m;i++)
            cout<<lastStart[i]<<" ";
        cout<<endl;
    }

}

 

202206-3 角色授权 

题目链接:角色授权

这题我只得了70分,原因是超时了 

 题解:这是一个比较复杂但是逻辑很简单的题,根据题目意思照着写就行,比较难的是代码比较多,所以分模块写,加上注释,以免写着写着忘记了。。。

#include<iostream>
#include<vector>
#include<sstream>
#include<unordered_set>
#include<unordered_map>
#include<utility>
using namespace std;
struct Character{
    string name;//角色名称
    unordered_set<string> operatorList;//操作清单
    unordered_set<string> resTypeList;//资源种类清单
    unordered_set<string> resList;//资源清单
    unordered_set<string> userList;//关联的用户
    unordered_set<string> groupList;//关联的组
};
//读取一个角色
Character getCharacter(){
    string info;
    getline(cin,info);
    istringstream iss(info);
    Character character;
    iss>>character.name;
    int opCount;//角色可操作个数
    iss>>opCount;
    for(int i=0;i<opCount;i++){
        string opName;//操作名称
        iss>>opName;
        character.operatorList.insert(std::move(opName));
    }
    int resTypeCount;//资源种类个数
    iss>>resTypeCount;
    for(int i=0;i<resTypeCount;i++){
        string resTypeName;
        iss>>resTypeName;
        character.resTypeList.insert(std::move(resTypeName));
    }
    int resCount;//资源个数
    iss>>resCount;
    for(int i=0;i<resCount;i++){
        string resName;
        iss>>resName;
        character.resList.insert(std::move(resName));
    }
    return character;
}
//读取关联信息
void getLinkInfo(unordered_map<string,Character> &nameMap){
    string info;
    getline(cin,info);
    istringstream iss(info);
    string characterName;
    iss>>characterName;
    int count;//关联数
    iss>>count;
    for(int i=0;i<count;i++){
        char type;//是u还是g
        string name;//组名或用户名
        iss>>type>>name;
        if(type=='u'){
            nameMap[characterName].userList.insert(std::move(name));
        }
        else if(type=='g'){
            nameMap[characterName].groupList.insert(std::move(name));
        }
    }
}
//根据用户名和用户组返回对应角色列表
unordered_set<string> getCharacterList(const unordered_map<string,Character> &nameMap,const string &userName,const vector<string> &groups){
    unordered_set<string> ret;
    for(const auto &p:nameMap){
        const auto &userList=p.second.userList;
        const auto &groupList=p.second.groupList;
        if(userList.count(userName)){
            ret.insert(p.first);
            continue;
        }
        for(const string &gName:groups){
            if(groupList.count(gName)){
                ret.insert(p.first);
                break;
            }
        }
    }
    return ret;
}
int main(){
    int n,m,q;//分别表示角色数量,关联数,操作数
    cin>>n>>m>>q;
    string temp;
    getline(cin,temp);//这是为了把换行读掉
    unordered_map<string,Character> nameMap;//角色名到角色对象的映射
    //读取角色信息
    for(int i=0;i<n;i++){
        Character character=getCharacter();
        nameMap[character.name]=std::move(character);
    }
    //读取关联信息
    for(int i=0;i<m;i++){
        getLinkInfo(nameMap);
    }
    //开始判操作是否可行
    vector<bool> ans(q,false);
    for(int i=0;i<q;i++){
        string info;
        getline(cin,info);
        istringstream iss(info);
        string userName;
        int count;//所属组数
        iss>>userName>>count;
        vector<string> groups(count);
        for(string &str:groups)
            iss>>str;
        auto characters= getCharacterList(nameMap,userName,groups);//该用户对应的角色集合
        string opName,resTypeName,resName;
        iss>>opName>>resTypeName>>resName;
        //遍历所有角色,查询操作是否合法
        for(const string &characterName:characters){
            const auto &character=nameMap[characterName];
            if((character.operatorList.count("*")||character.operatorList.count(opName))
            &&(character.resTypeList.count("*")||character.resTypeList.count(resTypeName))
            &&(character.resList.empty()||character.resList.count(resName))){
                ans[i]=true;//该次操作合法
                break;
            }
        }
    }
    for(bool val:ans)
        cout<<val<<endl;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值