0011SkillUp

该博客介绍了如何解决一道来自AtCoder的算法问题0011SkillUp。怪人希望掌握M门算法,每门算法的掌握程度要超过X。每本书对应不同的价格和对算法的提升效果。博主通过遍历所有购买书籍的可能性,寻找满足条件的最低花费。如果存在解决方案,则计算出最小花费,否则返回-1。算法的时间复杂度为O(2^n),空间复杂度为O(n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Skill Up

编号:0011

试题来源:AtCoder

试题描述

怪人想要学习 M M M门算法,假设对于技艺的掌握程度是可以量化的,怪人的期望是对于这 M M M门算法,每一门的掌握程度都要大于 X X X。提高掌握程度的方法是读书,假设书店中共有 N N N本书,其中第 i i i本书的价格是 C i C_i Ci,对于第 j j j门算法的提升程度是 A i , j A_{i,j} Ai,j。以上均为已知,判断能否满足怪人的期望,如果可以的话,请问最少花费?

取值范围:

  • 所有值都是整数
  • 1 ≤ N , M ≤ 12 1\leq N, M\leq 12 1N,M12
  • 1 ≤ X ≤ 1 0 5 1\leq X \leq 10^5 1X105
  • 1 ≤ C i ≤ 1 0 5 1\leq C_i \leq 10^5 1Ci105
  • 0 ≤ A i , j ≤ 1 0 5 0\leq A_{i,j}\leq 10^5 0Ai,j105

输入格式

N M X

C 1 C_1 C1 A 1 , 1 A_{1,1} A1,1 A 1 , 2 A_{1,2} A1,2 … \dotso A 1 , M A_{1,M} A1,M

⋮ \vdots

C N C_N CN A N , 1 A_{N,1} AN,1 A N , 2 A_{N,2} AN,2 ⋯ \cdots A N , M A_{N,M} AN,M

解答算法

算法思路

从头开始遍历,对于每本书都有买和不买两种可能,将 2 N 2^N 2N中可能全部遍历一遍,取其中的满足条件的最小价格,如果没有能够满足条件的,就输出-1

遍历过程利用的是func函数,两个参数nnsum分别表示当前已经遍历到第几本书,和当前遍历过的价格和,对于第i本书,只有买和不买两种可能,因此func(nn,sum)继续递归调用只会有两种情况,买func(nn+1,sum+c[nn]),不买func(nn+1,sum),注意在买的时候,同时要改变我们要提升的技能的点数。

代码实现

#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<algorithm>
#include<functional>
#define MM 2000000000
void func(int, int);
int n, m, x, c[12], a[12][12], wk[12], mn;//n、m、x、c、a都是题目意思,wk表示m门技能的掌握程度,mn表示最后的付款
using namespace std;
int main(void)
{
	int i, j;
	scanf("%d %d %d", &n, &m, &x);
	for (i = 0; i < n; i++) {
		scanf("%d", &c[i]);
		for (j = 0; j < m; j++) {
			scanf("%d", &a[i][j]);
		}
	}
	mn = MM;    //初始给mn赋一个极大值,如果最后还是这个极大值,说明没有满足条件的解,输出-1就好
	for (i = 0; i < m; i++)	wk[i] = 0;  //把掌握程度置0
	func(0, 0);  //开始调用
	if (mn != MM)	printf("%d\n", mn);
	else printf("-1\n");
	return 0;
}
void func(int nn, int sum)  //把每一种情况都遍历了一遍
{
	int i, flg;
	if (nn == n) {  //递归到尽头
		flg = 1;
		for (i = 0; i < m; i++) {  //判断是否满足掌握程度大于X
			if (wk[i] < x) {
				flg = 0;	break;
			}
		}
		if (flg == 1)	mn = min(mn, sum);  //满足的话,更新mn
	}
	else {
		func(nn + 1, sum);    //不买第nn本书
		for (i = 0; i < m; i++) {
			wk[i] += a[nn][i];
		}
		func(nn + 1, sum + c[nn]);  //买第nn本书
		for (i = 0; i < m; i++) {
			wk[i] -= a[nn][i];
		}
	}
}

复杂度分析

  • 时间复杂度:整个过程中对所有的 2 n 2^n 2n中情况均遍历了一遍,因此时间复杂度 O ( 2 n ) O(2^n) O(2n)
  • 空间复杂度:主要是递归调用的栈空间,栈空间深度为 n n n,因此空间复杂度 O ( n ) O(n) O(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值