2019 CSP-S1 提高组第1轮 三、完善程序(单选题,每题 3 分,共计 30 分)1、匠人的自我修养

该文章描述了一个关于技术学习路径优化的问题,其中涉及到一个匠人学习新技术的条件和经验值增长。给定每个技术的需求和奖励,以及匠人的初始经验值,目标是确定他最多能学会多少个新技术。程序以O(n^2)时间复杂度解决此问题,通过检查解锁条件(前置技术已解锁且经验足够)并更新解锁状态来迭代找到答案。
摘要由CSDN通过智能技术生成

一个匠人决定要学习 n 个新技术,要想成功学习一个新技术,
他不仅要拥有一定的经验值,而且还必须要先学会若干个相关的技术。学会一个
新技术之后,他的经验值会增加一个对应的值。给定每个技术的学习条件和习得
后获得的经验值,给定他已有的经验值,请问他最多能学会多少个新技术。

输入
第一行有两个数,分别为新技术个数 n(1≤n≤103),以及已有经验值(≤10^7).

接下来 n 行。

第 i 行的两个整数,分别表示学习第 i 个技术所需的最低经验值(≤10^7),

以及学会第 i 个技术后可获得的经验值(≤10^4)。

接下来 n 行。
第 i 行的第一个数 mi(0≤mi<n),表示第 i 个技术的相关技术数量。

紧跟着 m 个两两不同的数,表示第 i 个技术的相关技术编号,

输出最多能学会的新技术个数。

下面的程序已 O(n^2)的时间复杂完成这个问题,试补全程序。



#include<cstdio>
using namespace std;
const int maxn = 1001;

int n;
//前置技能的数量
int cnt[maxn];
//child数组用于记录每个技能的后置技能的编号
int child [maxn][maxn];
//unlock 作用是看是否能解锁任务。
int unlock[maxn];
int threshold[maxn], bonus[maxn];
int points;
bool find()
{
    int target = -1;
    for (int i = 1; i <= n; ++i)
    {    //if(① && ②){
        /*
		①解析:unlock 作用是看是否能解锁任务。
		根据对问题 5 的分析,在未解锁前它的
		值是还有几个依赖任务未解锁。
		那么解锁条件当然是 0 个依赖任务,
		因此是等于 0
		
		②解析:很简单,解锁条件之二,经验点要大于等于任务的需求点
        */
        if( unlock[i] == 0 && points >= threshold[i])
		{
        	
            target = i;
            break;
    	}	
    }
    
    if(target == -1)
        return false;
    
    unlock[target] = -1;
    points += bonus[target];//③
    /*
    解析:经验点增加。A 肯定不对,target 后面还要用。
	B 不对,因为 cnt[i]是依赖 i 的任务。
	C 也不对,bonus 是只读的
    */
    //cnt[target]:前置技能target的数量
	//child数组用于记录每个技能的后置技能的编号
	for (int i = 0; i < cnt[target]; ++i)
        unlock[child[target][i]] -= 1;//④
    /*
    解析:从前面分析看出 unlock 是依赖的还没解锁的任务数,
	解锁一个任务,
	所有依赖这个任务的 unlock 值都要减 1
    */
    return true;
}

int main( void )
{
    
    //新技术个数 n(1≤n≤103),以及已有经验值(≤10^7).
	scanf("%d%d", &n, &points);
    
	for (int i = 1; i <= n; ++i)
	{
        //前置技能i的数量
		cnt[i] = 0;
	
		//第 i 行的两个整数,
		//分别表示学习第 i 个技术所需的最低经验值(≤10^7)
		//,以及学会第 i 个技术后可获得的经验值(≤10^4)。
		scanf("%d%d", &threshold[i], &bonus[i]);
    }
    
    for (int i = 1; i <= n; ++i)
	{
        int m;
        //输入第 i个技术的相关技术数量。即前置技能 
		scanf("%d", &m);
		
        //初始化每个技能尚未解锁的前置技能数
		unlock[i] = m; //⑤
        /*
        解析:m 是任务依赖的任务数,
		从前面代码看出当 unlock[i]为-1 时表示解锁成功,那么 D 不对。
		A 的话 cnt[i]此时还没完成赋值,也不对。
		C 有迷惑性,认为 unlock是布尔值,
		但看题目 m 个依赖任务完成才能解锁该任务,
		所以不是单纯的布尔,
		需要每解锁一个前置任务就将 unlock 减 1,直到为 0
        */
        for (int j = 0; j < m; ++j)
		{
            int fa;
            //紧跟着 m 个两两不同的数,表示第 i 个技术的相关技术编号,
			//输出最多能学会的新技术个数。
			scanf("%d", &fa);
            
			//child数组用于记录每个技能的后置技能的编号
			child[fa][cnt[fa]] = i;
            
			//前置技能fa的数量 
			++cnt[fa];
        }
    }

    int ans = 0;
    while( find() )
        ++ans;

    //输出最多能学会的新技术个数。
	printf("%d\n", ans);
    return 0;
}
/*
①处应填()
||| unlock[i] <= 0
||| unlock[i] >= 0
||| unlock[i] == 0
||| unlock[i] == -1
②处应填()
||| threshold[i] > points
||| threshold[i] >= points
||| points > threshold[i]
||| points >= threshold[i]
③处应填()
||| target = -1
||| --cnt[target]
||| bonus[target] = 0
||| points += bonus[target]
④处应填()
||| cnt[child[target][i]] -= 1
||| cnt[child[target][i]] = 0
||| unlock[child[target][i]] -= 1
||| unlock[child[target][i]] = 0
⑤处应填()
||| unlock[i] = cnt[i]
||| unlock[i] = m
||| unlock[i] = 0
||| unlock[i] = -1
1.
 A. unlock[i] <= 0
 B. unlock[i] >= 0
 C. unlock[i] == 0
 D. unlock[i] == -1
2.
 A. threshold[i] > points
 B. threshold[i] >= points
 C. points > threshold[i]
 D. points >= threshold[i]
3.
 A. target = -1
 B. --cnt[target]
 C. bonus[target] = 0
 D. points += bonus[target]
4.
 A. cnt[child[target][i]] -= 1
 B. cnt[child[target][i]] = 0
 C. unlock[child[target][i]] -= 1
 D. unlock[child[target][i]] = 0
5.
 A. unlock[i] = cnt[i]
 B. unlock[i] = m
 C. unlock[i] = 0
 D. unlock[i] = -1

本题共 15 分
*/



CSP-J CSP-S NOI初赛

https://blog.csdn.net/dllglvzhenfeng/category_11823100.html

CCF关于举办CSP-J1 CSP-S1 初赛的报名通知

CCF关于举办CSP-J1 CSP-S1 初赛的报名通知-CSDN博客

CSP-J CSP-S初赛相关知识汇总

CSP-J CSP-S初赛相关知识汇总_csp-j初赛知识精选-CSDN博客

CSP-J CSP-S 初赛模拟题

CSP-J CSP-S 初赛模拟题_csp-s初赛模拟题_dllglvzhenfeng的博客-CSDN博客

2021年CSP-S初赛模拟题

2021年CSP-S初赛模拟题_2021csp模拟题_dllglvzhenfeng的博客-CSDN博客

洛谷2020、2021、2022 CSP-J1 CSP-S1 第1轮 初赛模拟

洛谷2020、2021、2022 CSP-J1 CSP-S1 第1轮 初赛模拟_dllglvzhenfeng的博客-CSDN博客






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dllglvzhenfeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值