一个匠人决定要学习 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初赛
CCF关于举办CSP-J1 CSP-S1 初赛的报名通知
CSP-J CSP-S初赛相关知识汇总
CSP-J CSP-S 初赛模拟题
2021年CSP-S初赛模拟题
洛谷2020、2021、2022 CSP-J1 CSP-S1 第1轮 初赛模拟
洛谷2020、2021、2022 CSP-J1 CSP-S1 第1轮 初赛模拟_dllglvzhenfeng的博客-CSDN博客