不知名题目

 全排列

题目描述

对1~ n 的 n个整数进行全排列(n<=9),编写程序输出所有可能的排列组合. 用递归算法实现.

输入

输入n

输出

输入n个整数的所有可能的排列组合.

样例输入

3

样例输出

   1   2   3

   1   3   2

   2   1   3

   2   3   1

   3   2   1

   3   1   2

//全排列生成器
#include <iostream>
#include <vector>
#include<iomanip>
using namespace std;

void permute(vector<int>& nums, int start, vector<vector<int>>& result)
{
	if (start == nums.size() - 1)
	{
		result.push_back(nums);
		return;
	}

	for (int i = start; i < nums.size(); ++i)
	{
		swap(nums[start], nums[i]);
		permute(nums, start + 1, result);
		swap(nums[start], nums[i]); // 回溯
	}
}

void printPermutations(const vector<vector<int>>& result)
{
	for (const auto& perm : result)
	{
		for (int num : perm)
		{
			cout << setw(4) << num;
		}
		cout << endl;
	}
}

int main()
{
	int n;
	cin >> n;
	if (n < 1 || n > 9)
	{
		return 1;
	}
	vector<int> nums(n);
	for (int i = 0; i < n; ++i)
	{
		nums[i] = i + 1;
	}
	vector<std::vector<int>> result;
	permute(nums, 0, result);
	printPermutations(result);

	return 0;
}

提取整数

题目描述

输入一个字符串,内有数字和非数字字符,例如:

A123x456 17960?302tab5876

将其中连续的数字作为一个整数,依次存放到一数组a中。例如,123放在a[0],456放在a[1]…统计共有多少个整数,并输出这些数。要求用指针方法处理。

输入格式

输入字符串,内有数字和非数字字符, 字符串长度不会超过1024。

输出格式

输出提取的整数,输出一共有多少个整数。

样例输入

A123x456 17960?302tab5876

样例输出

123

456

17960

302

5876

5 integers in total

//从字符串中提取整数

#include <iostream>
#include <vector>
#include <string>
using namespace std;

void extractIntegers(const string& input, vector<int>& numbers)
{
    int num = 0;          // 用于存储当前正在累加的数字
    bool inNumber = false; // 标记当前是否在处理一个数字

    for (const char* p = input.c_str(); *p != '\0'; ++p) 
    {
        if (*p >= '0' && *p <= '9')
        { // 检查当前字符是否为数字
            num = num * 10 + (*p - '0'); // 将当前字符转换为数字并累加到num
            inNumber = true;           // 设置标志表示正在处理数字
        }
        else 
        {
            if (inNumber) 
            { // 如果之前在处理数字但现在遇到了非数字字符
                numbers.push_back(num); // 将累加的数字存入向量
                num = 0;              // 重置num以便处理下一个数字
                inNumber = false;     // 清除标志
            }
        }
    }

    // 检查最后一个字符是否是数字,如果是,则将其存入向量
    if (inNumber) 
    {
        numbers.push_back(num);
    }
}

int main()
{
    string input;
    cout << "请输入一个字符串: ";
    getline(std::cin, input);

    vector<int> numbers;
    extractIntegers(input, numbers);

    for (int num : numbers)
    {
        cout << num << std::endl;
    }
    
    cout << numbers.size() << " integers in total" << endl;

    return 0;
}

详细解析一下这个递归函数 permute 的作用和工作原理。

函数签名

void permute(vector<int>& nums, int start, vector<vector<int>>& result)
  • vector<int>& nums: 这是要进行全排列的整数向量。使用引用传递,以避免复制整个向量。
  • int start: 当前处理的起始索引。初始调用时为0。
  • vector<vector<int>>& result: 存储所有生成的排列组合的结果集。使用引用传递,以便在递归过程中累积结果。

函数逻辑

  1. 基准条件

    if (start == nums.size() - 1)
    {
        result.push_back(nums);
        return;
    }
    • 当 start 达到 nums.size() - 1 时,表示当前排列已经完成(即从 start 到最后一个元素的所有位置都已经确定)。
    • 此时,将当前排列 nums 添加到结果集 result 中。
    • 返回,结束当前递归调用。
  2. 递归过程

    for (int i = start; i < nums.size(); ++i)
    {
        swap(nums[start], nums[i]);
        permute(nums, start + 1, result);
        swap(nums[start], nums[i]); // 回溯
    }
    • 使用一个循环遍历从 start 到 nums.size() - 1 的每一个位置 i
    • 在每次迭代中,交换 nums[start] 和 nums[i],从而尝试不同的排列组合。
    • 调用 permute(nums, start + 1, result) 继续处理下一个位置的排列。
    • 交换回 nums[start] 和 nums[i],恢复原状,以便尝试其他可能的排列组合(这就是回溯的过程)。

具体步骤举例

假设输入 nums = {1, 2, 3},我们来逐步分析递归过程:

  1. 初始调用:

    • permute({1, 2, 3}, 0, result)
  2. 第一层递归 (start = 0):

    • i = 0:
      • 交换 nums[0] 和 nums[0](不变),得到 {1, 2, 3}
      • 调用 permute({1, 2, 3}, 1, result)
    • i = 1:
      • 交换 nums[0] 和 nums[1],得到 {2, 1, 3}
      • 调用 permute({2, 1, 3}, 1, result)
    • i = 2:
      • 交换 nums[0] 和 nums[2],得到 {3, 1, 2}
      • 调用 permute({3, 1, 2}, 1, result)
  3. 第二层递归 (start = 1):

    • 对于 {1, 2, 3}:
      • i = 1:
        • 交换 nums[1] 和 nums[1](不变),得到 {1, 2, 3}
        • 调用 permute({1, 2, 3}, 2, result)
      • i = 2:
        • 交换 nums[1] 和 nums[2],得到 {1, 3, 2}
        • 调用 permute({1, 3, 2}, 2, result)
    • 对于 {2, 1, 3}:
      • i = 1:
        • 交换 nums[1] 和 nums[1](不变),得到 {2, 1, 3}
        • 调用 permute({2, 1, 3}, 2, result)
      • i = 2:
        • 交换 nums[1] 和 nums[2],得到 {2, 3, 1}
        • 调用 permute({2, 3, 1}, 2, result)
    • 对于 {3, 1, 2}:
      • i = 1:
        • 交换 nums[1] 和 nums[1](不变),得到 {3, 1, 2}
        • 调用 permute({3, 1, 2}, 2, result)
      • i = 2:
        • 交换 nums[1] 和 nums[2],得到 {3, 2, 1}
        • 调用 permute({3, 2, 1}, 2, result)
  4. 第三层递归 (start = 2):

    • 对于 {1, 2, 3}:
      • i = 2:
        • 交换 nums[2] 和 nums[2](不变),得到 {1, 2, 3}
        • 基准条件满足,将 {1, 2, 3} 添加到 result
    • 对于 {1, 3, 2}:
      • i = 2:
        • 交换 nums[2] 和 nums[2](不变),得到 {1, 3, 2}
        • 基准条件满足,将 {1, 3, 2} 添加到 result
    • 对于 {2, 1, 3}:
      • i = 2:
        • 交换 nums[2] 和 nums[2](不变),得到 {2, 1, 3}
        • 基准条件满足,将 {2, 1, 3} 添加到 result
    • 对于 {2, 3, 1}:
      • i = 2:
        • 交换 nums[2] 和 nums[2](不变),得到 {2, 3, 1}
        • 基准条件满足,将 {2, 3, 1} 添加到 result
    • 对于 {3, 1, 2}:
      • i = 2:
        • 交换 nums[2] 和 nums[2](不变),得到 {3, 1, 2}
        • 基准条件满足,将 {3, 1, 2} 添加到 result
    • 对于 {3, 2, 1}:
      • i = 2:
        • 交换 nums[2] 和 nums[2](不变),得到 {3, 2, 1}
        • 基准条件满足,将 {3, 2, 1} 添加到 result

总结

  • 递归思想: 通过不断固定当前位置的元素,并递归地对剩余部分进行全排列,最终生成所有可能的排列组合。
  • 回溯机制: 在每次递归返回后,恢复之前的状态(即撤销交换操作),以便尝试其他可能的排列组合。
  • 基准条件: 当 start 达到 nums.size() - 1 时,表示一个完整的排列已完成,将其添加到结果集中。

负数计算

Create a structure named Complex to represent a complex number with real and imaginary parts. Write a C/C++ program to add, substrate, multiply, or divide two complex numbers.

Input:

Input two complex numbers using format a+bi, and your operation option.

Output:

Output the operation result of two complex numbers.

Sample Input & Output:

Input first Complex Number using format a+bi

3.5+8.6i

Input second Complex Number using format a+bi

-8.8-10.8i

Input your operation option of the Complex Number: + , - , * , or /

+

The result of two Complex Numbers after + operation is:

-5.30-2.20i

#include <iostream>
#include <sstream>

using namespace std;

struct Complex {
    double real;
    double imag;

    Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}

    friend ostream& operator<<(ostream& os, const Complex& c) {
        os << c.real << (c.imag >= 0 ? "+" : "") << c.imag << "i";
        return os;
    }
};

Complex parseComplex(const string& str) {
    double real, imag;
    char op;
    istringstream iss(str);
    iss >> real >> op >> imag;
    if (op == '-') imag = -imag;
    return Complex(real, imag);
}

Complex add(const Complex& c1, const Complex& c2) {
    return Complex(c1.real + c2.real, c1.imag + c2.imag);
}

Complex subtract(const Complex& c1, const Complex& c2) {
    return Complex(c1.real - c2.real, c1.imag - c2.imag);
}

Complex multiply(const Complex& c1, const Complex& c2) {
    return Complex(c1.real * c2.real - c1.imag * c2.imag, c1.real * c2.imag + c1.imag * c2.real);
}

Complex divide(const Complex& c1, const Complex& c2) {
    double denominator = c2.real * c2.real + c2.imag * c2.imag;
    return Complex((c1.real * c2.real + c1.imag * c2.imag) / denominator,
                   (c1.imag * c2.real - c1.real * c2.imag) / denominator);
}

int main() {
    string input1, input2, operation;
    
    cout << "Input first Complex Number using format a+bi\n";
    getline(cin, input1);
    Complex c1 = parseComplex(input1);

    cout << "Input second Complex Number using format a+bi\n";
    getline(cin, input2);
    Complex c2 = parseComplex(input2);

    cout << "Input your operation option of the Complex Number: + , - , * , or /\n";
    cin >> operation;

    Complex result;
    if (operation == "+") {
        result = add(c1, c2);
    } else if (operation == "-") {
        result = subtract(c1, c2);
    } else if (operation == "*") {
        result = multiply(c1, c2);
    } else if (operation == "/") {
        result = divide(c1, c2);
    } else {
        cerr << "Invalid operation\n";
        return 1;
    }

    cout << "The result of two Complex Numbers after " << operation << " operation is:\n" << result << endl;
    return 0;
}

结构体定义

struct Complex {
    double real;
    double imag;

    Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}

    friend ostream& operator<<(ostream& os, const Complex& c) {
        os << c.real << (c.imag >= 0 ? "+" : "") << c.imag << "i";
        return os;
    }
};

成员变量

    double real;
    double imag;
  • double real;: 表示复数的实部。
  • double imag;: 表示复数的虚部。

构造函数

    Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
  • Complex(double r = 0.0, double i = 0.0): 这是一个带默认参数的构造函数。它可以接受两个参数 r 和 i,分别用于初始化 real 和 imag
    • 如果没有提供参数,则使用默认值 0.0
    • 使用成员初始化列表 : real(r), imag(i) 来初始化成员变量 real 和 imag
  • 示例:
    • Complex c1; 创建一个复数对象 c1,其 real 和 imag 都为 0.0
    • Complex c2(3.5, 8.6); 创建一个复数对象 c2,其 real 为 3.5imag 为 8.6

友元运算符重载

    friend ostream& operator<<(ostream& os, const Complex& c) {
        os << c.real << (c.imag >= 0 ? "+" : "") << c.imag << "i";
        return os;
    }
  • friend ostream& operator<<(ostream& os, const Complex& c): 这是一个友元函数,通过重载输出流运算符 <<,使得可以直接使用 cout 输出 Complex 对象,并按照标准格式(如 a+bia-bi)显示复数。
    • friend 关键字: 声明该函数为 Complex 的友元函数,使其可以访问 Complex 的私有和保护成员。
    • ostream& operator<<(ostream& os, const Complex& c): 定义了一个名为 operator<< 的函数,它接受两个参数:
      • ostream& os: 输出流对象,通常是 cout
      • const Complex& c: 要输出的 Complex 对象。
    • 函数体:
      • os << c.real: 将 Complex 对象的实部 real 输出到流 os
      • (c.imag >= 0 ? "+" : ""): 使用三元运算符来决定是否输出加号 +。如果虚部 imag 大于或等于 0,则输出一个加号 +;否则不输出任何符号。例如,如果 c.imag 是 8.6,则输出 +。如果 c.imag 是 -8.6,则不输出任何符号。
      • << c.imag << "i": 将 Complex 对象的虚部 imag 和后缀 i 输出到流 os。例如,如果 c.imag 是 8.6,则输出 8.6i。如果 c.imag 是 -8.6,则输出 -8.6i
      • return os;: 返回输出流对象 os,以便支持链式调用(例如 cout << c1 << c2;)。   

示例:

假设我们有一个 Complex 对象 c(3.5, 8.6),当执行 cout << c; 时,会发生以下步骤:

  1. 调用重载的 operator<< 函数。
  2. os << c.real 输出 3.5
  3. (c.imag >= 0 ? "+" : "") 判断 c.imag 是否大于或等于 0,结果为 true,因此输出 +
  4. << c.imag << "i" 输出 8.6i
  5. 最终输出结果为 3.5+8.6i

再比如,假设我们有一个 Complex 对象 c(-8.8, -10.8),当执行 cout << c; 时,会发生以下步骤:

  1. 调用重载的 operator<< 函数。
  2. os << c.real 输出 -8.8
  3. (c.imag >= 0 ? "+" : "") 判断 c.imag 是否大于或等于 0,结果为 false,因此不输出任何符号。
  4. << c.imag << "i" 输出 -10.8i
  5. 最终输出结果为 -8.8-10.8i

函数定义

Complex parseComplex(const string& str) {}
  • Complex: 这是函数的返回类型。函数将解析输入字符串并返回一个 Complex 类型的对象。
  • parseComplex: 这是函数的名称,表示该函数用于解析复数字符串。
  • (const string& str): 这是函数的参数列表。它接受一个常量引用类型的 string 参数 str,表示要解析的复数字符串。

变量声明

    double real, imag;
    char op;
  • double real, imag;: 声明两个双精度浮点数变量 real 和 imag,分别用于存储复数的实部和虚部。
  • char op;: 声明一个字符变量 op,用于存储操作符(通常是 '+' 或 '-')。

字符串流初始化

    istringstream iss(str);
  • istringstream iss(str);: 创建一个 istringstream 对象 iss,并将传入的字符串 str 初始化给它。istringstream 是 C++ 标准库中的一个类,用于从字符串中读取数据,类似于从文件或标准输入读取数据的方式。

解析字符串

    iss >> real >> op >> imag;
  • iss >> real >> op >> imag;: 使用 >> 操作符从 iss 中依次提取实部 real、操作符 op 和虚部 imag
    • 例如,如果输入字符串是 "3.5+8.6i",则:
      • real 将被赋值为 3.5
      • op 将被赋值为 '+'
      • imag 将被赋值为 8.6

处理负虚部

    if (op == '-') imag = -imag;
  • if (op == '-') imag = -imag;: 如果操作符 op 是 '-',则将虚部 imag 取反。
    • 继续上面的例子,如果输入字符串是 "-8.8-10.8i",则:
      • real 将被赋值为 -8.8
      • op 将被赋值为 '-'
      • imag 将被赋值为 10.8(因为 op 是 '-',所以 imag 被取反)

返回结果

    return Complex(real, imag);
}
  • return Complex(real, imag);: 使用解析得到的实部 real 和虚部 imag 构造一个新的 Complex 对象,并将其返回。

学习收益计算

题目描述

期末考试一共有 𝑛门课程,huaijiao 需要在有限时间内尽可能合理地安排速通计划,来让自己的绩点最大化。

已知第 𝑖门课程的学分 𝑐𝑖和难度系数 𝑘𝑖​,huaijiao 如果花费 𝑥天来速通第 𝑖门课程,那么他将取得的成绩 𝑤𝑖=min⁡(1,𝑥/𝑘𝑖)×100。

huaijiao 最后的总成绩 𝑊=∑𝑖=1𝑛(𝑤𝑖×𝑐𝑖)。

huaijiao 现在一点没学,距离期末考试只剩下 𝑀M 天,每天 huaijiao 只能专心学一门,请你帮帮他最大化他的总成绩。

输入格式

第一行两个正整数 𝑛,𝑀分别表示总共有多少门课程和距离期末考试还剩下多少天。

第二行 𝑛个正整数,表示每门课程的学分:𝑐1,𝑐2,⋯ ,𝑐𝑛。

第三行 𝑛个正整数,表示每门课程的难度:𝑘1,𝑘2,⋯ ,𝑘𝑛。

输出格式

输出一个实数,保留四位小数,表示最大的总成绩。

输入输出样例

输入 #1

4 8
2 1 10 10
4 9 5 2

输出 #1

2050.0000

输入 #2

10 19
1 10 3 3 1 10 2 7 8 6
3 2 1 2 7 9 7 6 4 7

输出 #2

3544.4444

输入 #3

8 18
4 6 4 1 3 8 9 3
6 9 6 7 5 9 8 3

输出 #3

1822.2222

代码

#include<iostream>
#include<vector>
#include<iomanip>
#include<algorithm>
using namespace std;

struct Course
{
	int c;
	int k;
	double unitvalue;//单位时间的收益。学分除以难度系数
};

//按单位时间收益从高到底排序课程
bool comparevalue(const Course& a, const Course& b)
{
	return a.unitvalue > b.unitvalue;
}

int main()
{
	int n, M;
	cin >> n >> M;
	
	vector<Course>course(n);
	for (int i = 0; i < n; i++)
	{
		cin >> course[i].c;
	}
	for (int i = 0; i < n; i++)
	{
		cin >> course[i].k;
		course[i].unitvalue = static_cast<double>(course[i].c) / course[i].k;
	}

	//按单位时间收益的大小排序,排序的依据是comparevalue函数
	sort(course.begin(), course.end(), comparevalue);

	double totalsorce = 0.0;
	for (int i = 0; i < n; i++)
	{
		if (M == 0)break;
		double studydays = min(M, static_cast<int>(course[i].k));
		double sorce = min(1.0, studydays / course[i].k) * 100.0 * course[i].c;

		totalsorce += sorce;
		M -= studydays;
	}
	
	cout << fixed << setprecision(4) <<  totalsorce << endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值