一、输入格式
1.1单组输入
#include<iostream>
using namespace std;
int main()
{
int a, b;
cin >> a >> b;
cout << a + b << endl;
return 0;
}
1.2多组输入,未知组数
#include<iostream>
using namespace std;
int main()
{
int a, b;
while(cin >> a >> b)
{
cout << a + b << endl;
}
return 0;
}
1.3多组输入,已知组数
#include<iostream>
using namespace std;
int main()
{
int n; // 指定组数
cin >> n;
while(n--)
{
int a, b;
cin >> a >> b;
cout << a+b << endl;
}
return 0;
}
1.4多组输入,指定跳出
#include<iostream>
using namespace std;
int main()
{
int a, b;
while(cin >> a >> b)
{
if(a == 0 && b == 0) //指定条件,输入0,0时跳出循环
{
break;
}
cout << a+b << endl;
}
return 0;
}
二、暴力求解
2.1枚举
2.1.1 abc
#include<iostream>
using namespace std;
int main()
{
//abc+bcc=532
//问题等价为100a+10b+c+100b+10c+c=100a+110b+12c=532
//枚举三个数字,判断是否符合条件
for(int a = 0; a < 10; a++)
{
for(int b = 0; b < 10; b++)
{
for(int c = 0; c < 10; c++)
{
if(100 * a + 110 * b + 12 * c == 532)
{
cout<<a<<" "<<b<<" "<<c<<endl;
}
}
}
}
}
2.1.2 反序数
#include<iostream>
using namespace std;
int getReverse(int number)
{
//求number的反序数,如1234的反序数为4321
//定义反序数,该数初始为0
int reverseNumber = 0;
while(number != 0)
{
reverseNumber *= 10;
reverseNumber += number % 10;
number /= 10;
}
return reverseNumber;
}
int main()
{
for (int i = 1000; i < 10000; i++)
{
if (getReverse(i) == i * 9)
{
cout<<i<<endl;
}
}
}
2.2模拟
2.2.1 输出梯形
#include<iostream>
using namespace std;
int main()
{
int h; //梯形的高度
cin >> h;
//梯形的第一行有h个*,第h行有h+2(h-1)个*,每行比上一行多两个*
//对于梯形的第i行,该行有h+2(i-1)个*,有h+2(h-1)-[h+2(i-1)]=2(h-i)个空格
for(int i = 0; i < h; i++){
for(int j = 0; j < h+2*(h-1); j++){
if(j < 2*(h-i-1)){
cout<<" ";
}
else{
cout<<"*";
}
}
cout<<endl;
}
return 0;
}
2.2.2 叠筐
2.2.3 今年的第几天?
#include<iostream>
using namespace std;
int dayTable[2][12] = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},//平年
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},//闰年
};
bool isLeapYear(int year){
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main(){
int year, month, day;
while(cin>>year>>month>>day){
int row = isLeapYear(year);
int n = 0;
for(int i = 0; i < month-1; i++){
n += dayTable[row][i];
}
n += day;
cout<<n<<endl;
}
return 0;
}
2.2.4 打印日期
#include<iostream>
#include<iomanip>
using namespace std;
int dayTable[2][12] = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},//平年
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},//闰年
};
bool isLeapYear(int year){
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main(){
int year, n;
while(cin>>year>>n){
int row = isLeapYear(year);
int month = 0;
while(n > dayTable[row][month]){
n -= dayTable[row][month];
month++;
}
month++;
cout<<year<<"-"<<setfill('0')<<setw(2)<<month<<"-"<<setfill('0')<<setw(2)<<n<<endl;
}
return 0;
}
2.2.5 手机键盘
#include<iostream>
#include<iomanip>
using namespace std;
//记录各个字母需要按键的次数
int keyTable[26] = {1, 2, 3, //abc
1, 2, 3, //def
1, 2, 3, //ghi
1, 2, 3, //jkl
1, 2, 3, //mno
1, 2, 3, 4,//pqrs
1, 2, 3, //tuv
1, 2, 3, 4 //wxyz
};
int main(){
string str;
while(cin>>str){
int n = 0;
for(int i = 0; i < str.length(); i++){
n += keyTable[str[i]-'a'];
//判断连续的两个字母是否在同一按键上
if(i != 0 && str[i] - str[i-1] == keyTable[str[i]-'a'] - keyTable[str[i-1]-'a']){
n += 2;
}
}
cout<<n<<endl;
}
return 0;
}
三、排序
3.1 基础排序
3.1.1 成绩排名
#include<iostream>
#include<algorithm>
using namespace std;
struct Student{
int number;
int score;
};
bool compare(Student s1, Student s2){
if (s1.score == s2.score){
return s1.number < s2.number;
} else {
return s1.score < s2.score;
}
}
int main(){
int n;
cin>>n;
Student students[n];
for(int i = 0; i < n; i++){
int num, sre;
cin>>num>>sre;
students[i].number = num;
students[i].score = sre;
}
sort(students, students + n, compare);
for(int i = 0; i < n; i++){
cout<<students[i].number<<" "<<students[i].score<<endl;
}
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
struct Student{
int number;
int score;
bool operator< (Student student) const{
if(score == student.score){
return number < student.number;
} else {
return score < student.score;
}
}
};
int main(){
int n;
cin>>n;
Student students[n];
for(int i = 0; i < n; i++){
int num, sre;
cin>>num>>sre;
students[i].number = num;
students[i].score = sre;
}
sort(students, students + n);
for(int i = 0; i < n; i++){
cout<<students[i].number<<" "<<students[i].score<<endl;
}
return 0;
}
3.1.2 整数奇偶排序
#include<iostream>
#include<algorithm>
using namespace std;
int arr[10];
bool compare(int x, int y){
//输入10个整数,彼此以空格分隔。重新排序以后输出(也按空格分隔),要求:
//1.先输出其中的奇数,并按从大到小排列;
//2.然后输出其中的偶数,并按从小到大排列。
if(x % 2 == 1 && y % 2 == 1){
//x和y都是奇数,从大到小排序
return x > y;
} else if (x % 2 == 0 && y % 2 == 0){
//x和y都是偶数,从小到大排序
return y > x;
} else {
//x和y一个是奇数,另一个是偶数,先输出奇数
return x % 2 > y % 2;
//若x是奇数,返回true;若y是奇数,返回false
}
}
int main(){
while(cin>>arr[0]){
for(int i = 1; i < 10; i++){
cin>>arr[i];
}
sort(arr, arr + 10, compare);
for(int i = 0; i < 10; i++){
cout<<arr[i]<<" ";
}
cout<<endl;
}
return 0;
}
3.2 扩展排序
3.2.1 sort(计数排序)
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1e6 + 10;
const int RANGE = 5e5;
int arr[MAXN];
int number[MAXN];
int main(){
int n,m;//n为输入元素的个数,m为输出元素的个数
while(cin>>n>>m){
memset(number, 0, sizeof(number));//清空辅助数组
for(int i = 0; i < n; i++){
cin>>arr[i];
//arr[i]的范围为(-5e5,5e5)
number[arr[i] + RANGE]++;
}
int index = 0;//重新赋值arr数组,保留number非0的元素
for(int i = 0; i < MAXN; i++){
while(number[i]--){
arr[index++] = i - RANGE;
}
}
for(int i = n-1; i >= n-m; i--){
if(i == n-m){
cout<<arr[i]<<endl;
} else{
cout<<arr[i]<<" ";
}
}
}
return 0;
}
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1e6 + 10;
const int RANGE = 5e5;
int arr[MAXN];
int number[MAXN];
int main(){
int n,m;//n为输入元素的个数,m为输出元素的个数
bool flag;
while(cin>>n>>m){
memset(number, 0, sizeof(number));//清空辅助数组
flag = true;
for(int i = 0; i < n; i++){
cin>>arr[i];
//arr[i]的范围为(-5e5,5e5)
number[arr[i] + RANGE]++;
}
for(int i = MAXN; i >=0; i--){
while(number[i]-- > 0){
//cout<<number[i]<<endl;
if(m-- > 1){
cout<<i - RANGE<<" ";
} else {
cout<<i - RANGE<<endl;
flag = false;
}
}
if (flag == false) {
break;
}
}
}
return 0;
}
3.2.2 逆序数
枚举,时间复杂度大
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1e5 + 10;
int arr[MAXN];
int main(){
int n;
while (cin>>n) {
long long answer = 0;
memset(arr, 0, sizeof(arr));
for (int i = 0; i < n; i++) {
cin>>arr[i];
}
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
if (arr[i] > arr[j]) {
answer++;
}
}
}
cout<<answer<<endl;
}
return 0;
}
利用归并排序
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1000 + 10;
int arr[MAXN];
int temp[MAXN];
int number;
void Combine(int left, int middle, int right){
int i = left;
int j = middle + 1;
int k = left;
while(i <= middle && j <= right){
if (arr[i] <= arr[j]) {
temp[k++] = arr[i++];
} else {
//前面的数大于后面的数,形成逆序对
number += middle + 1 - i;
temp[k++] = arr[j++];
}
}
while(i <= middle) {
temp[k++] = arr[i++];
}
while(j <= right) {
temp[k++] = arr[j++];
}
for(k = left; k <= right; k++){
arr[k] = temp[k];
}
}
void MergeSort(int left, int right){
if(left < right){
int middle = left + (right - left) / 2;
MergeSort(left, middle);
MergeSort(middle + 1, right);
Combine(left, middle, right);
}
}
int main(){
int n;
cin>>n;
for(int i = 0; i < n; i++){
cin>>arr[i];
}
number = 0;
MergeSort(0, n-1);
cout<<number;
return 0;
}
3.2.3 寻找第k大元素
快速排序
#include<iostream>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAXN = 1000 + 10;
int arr[MAXN];
int Partition(int left, int right){
//选择随机的基准元素
int random = left + rand() % (right - left + 1);
//将基准元素与第一个元素交换位置
swap(arr[left], arr[random]);
while(left < right){
//从右到左依次对比,直到右指针所指的元素小于左指针所指的元素
while(left < right && arr[left] <= arr[right]){
right--;
}
//此时,右指针所指的元素小于左指针所指的元素,交换两个指针
swap(arr[left], arr[right]);
//从左到右依次对比,直到左指针所指的元素大于右指针所指的元素
while(left < right && arr[left] <= arr[right]){
left++;
}
此时,左指针所指的元素大于右指针所指的元素,交换两个指针
swap(arr[left], arr[right]);
}
return left;
}
int QuickSort(int left, int right, int p){
if(left < right){
//获取随机选择的基准元素的位置
int position = Partition(left, right);
//如果该元素的位置小于第k大元素所在的位置,在该元素的右边继续查找
//如果该元素的位置大于第k大元素所在的位置,在该元素的右边继续查找
//如果该元素的位置正是需要寻找的第k大元素的位置,返回这个位置上的值
if(position < p){
QuickSort(position + 1, right, p);
} else if (position > p){
QuickSort(left, position - 1, p);
} else {
return arr[position];
}
}
}
int main(){
int n;
cin>>n;
for(int i = 0; i < n; i++){
cin>>arr[i];
}
int k;
cin>>k;
int answer = QuickSort(0, n-1, n-k);
cout<<answer;
return 0;
}
优先队列
#include<iostream>
#include<queue>
using namespace std;
priority_queue<int> arr;
int main(){
while (getchar() != ']') {
int number;
cin>>number;
arr.push(number);
}
int i = 1;
while (i < 3) {
arr.pop();
i++;
}
cout<<arr.top();
return 0;
}
3.3 基础查找
3.3.1 线性查找
#include<iostream>
using namespace std;
const int MAXN = 100 + 10;
int arr[MAXN];
bool LinearSearch(int n, int target){
for(int i = 0; i < n; i++){
if(arr[i] == target){
return true;
}
}
return false;
}
int main(){
//先指定数组长度
int n;
cin>>n;
//初始化数组
for(int i = 0; i < n; i++){
cin>>arr[i];
}
//输入待查找元素的个数
int m;
cin>>m;
while(m--){
int target;
cin>>target;
if(LinearSearch(n, target)){
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}
return 0;
}
3.3.2 二分查找
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100 + 10;
int arr[MAXN];
bool BinarySearch(int n, int target){
int left = 0;
int right = n - 1;
while(left <= right){
int middle = left + (right - left) / 2;
if (target == arr[middle]){
//已查找到目标元素
return true;
} else if(target < arr[middle]){
//在中间元素的左边查找
right = middle - 1;
} else {
//在中间元素的右边查找
left = middle + 1;
}
}
return false;
}
int main(){
//先指定数组长度
int n;
cin>>n;
//初始化数组
for(int i = 0; i < n; i++){
cin>>arr[i];
}
//输入待查找元素的个数
int m;
cin>>m;
while(m--){
int target;
cin>>target;
sort(arr, arr + n);
if(BinarySearch(n, target)){
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100 + 10;
int arr[MAXN];
int main(){
//先指定数组长度
int n;
cin>>n;
//初始化数组
for(int i = 0; i < n; i++){
cin>>arr[i];
}
//输入待查找元素的个数
int m;
cin>>m;
while(m--){
int target;
cin>>target;
//lower_bound返回大于或等于目标值的第一个位置(指针)
//upper_bound返回大于目标值的第一个位置(指针)
sort(arr, arr + n);
int position = lower_bound(arr, arr + n, target) - arr;
if(position != n && arr[position] == target){
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}
return 0;
}
3.3.3 散列查找
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100 + 10;
const int RANGE = 1e6 + 10;
int arr[MAXN];
bool hashTable[RANGE];
int main(){
//先指定数组长度
int n;
cin>>n;
//初始化数组
for(int i = 0; i < n; i++){
cin>>arr[i];
hashTable[arr[i]] = true;
}
//输入待查找元素的个数
int m;
cin>>m;
while(m--){
int target;
cin>>target;
if(hashTable[target]){
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}
return 0;
}
#include<iostream>
#include<unordered_map>
using namespace std;
const int MAXN = 100 + 10;
const int RANGE = 1e6 + 10;
int arr[MAXN];
unordered_map<int, bool> hashTable;
int main(){
//先指定数组长度
int n;
cin>>n;
//初始化数组
for(int i = 0; i < n; i++){
cin>>arr[i];
hashTable[arr[i]] = true;
}
//输入待查找元素的个数
int m;
cin>>m;
while(m--){
int target;
cin>>target;
if(hashTable[target]){
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}
return 0;
}
四、字符串
4.1 字符串操作
4.1.1 特殊乘法(遍历)
#include<iostream>
#include<string>
using namespace std;
int main(){
string str1, str2;
while(cin >> str1 >> str2){
int answer = 0;
for(int i = 0; i < str1.size(); i++){
for(int j = 0; j < str2.size(); j++){
answer += (str1[i] - '0') * (str2[j] - '0');
}
}
cout<<answer<<endl;
}
return 0;
}
4.1.2 简单密码(加密)
#include<iostream>
#include<string>
using namespace std;
int main(){
string str;
while(getline(cin, str)){
//如果输入的第一行为ENDOFINPUT则跳出循环
if(str == "ENDOFINPUT"){
break;
}
//输入待加密字符串
getline(cin, str);
for(int i = 0; i < str.size(); i++){
//对大写字母进行加密
if(str[i] >= 'A' && str[i] <= 'Z'){
//str[i] - 'A'得到大写字母在字母表中的位置
//(str[i] - 'A' - 5 + 26)%26得到加密后的字母在字母表的位置
//str[i] = (str[i] - 'A' - 5 + 26) % 26 + 'A'得到加密后的字母
str[i] = (str[i] - 'A' - 5 + 26) % 26 + 'A';
}
}
cout<<str<<endl;
getline(cin, str);
}
return 0;
}
4.1.3 统计字符(统计)
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int MAXN = 128;
int number[MAXN];
int main(){
string str1, str2;
while(getline(cin, str1)){
if(str1 == "#"){
break;
}
memset(number, 0, sizeof(number));
//输入str2,统计str2中各个字符出现的次数
getline(cin, str2);
for(int i = 0; i < str2.size(); i++){
//数组以字符为下标,实质就是用该字符的ASCII码作为下标
number[str2[i]]++;
}
for(int i = 0; i < str1.size(); i++){
cout<<str1[i]<<" "<<number[str1[i]]<<endl;
}
}
return 0;
}
4.2 字符串匹配
五、线性数据结构
5.1 向量
5.2 队列
5.2.1 猫狗收养所
#include<iostream>
#include<queue>
using namespace std;
struct Animal{
int number;//动物编号
int order;//动物进入收容所的次序
Animal(int n, int o) : number(n), order(o) {}
};
int main(){
queue<Animal> dogs;
queue<Animal> cats;
int n;//操作序列的次数
cin>>n;
int order = 0;//记录次序
for (int i = 0; i < n; i++){
int event;//event=1:有动物进入收容所,并定义编号;event=2,有人收养动物,并指明方法
cin>>event;
if(event == 1){
//收容动物,正数代表狗,负数代表猫
int number;
cin>>number;
if(number > 0){
dogs.push(Animal(number, order++));
} else if (number < 0){
cats.push(Animal(number, order++));
}
} else if (event == 2){
//收养动物,并指明方法
//way=0:收养第一个动物
//way=1:收养第一只狗
//way=-1;收养第一只猫
int way;
cin>>way;
if (way == 0 && !dogs.empty() && !cats.empty()){
if (dogs.front().order < cats.front().order){
cout<<dogs.front().number<<" ";
dogs.pop();
} else {
cout<<cats.front().number<<" ";
cats.pop();
}
} else if (way == 0 && !dogs.empty() && cats.empty()){
cout<<dogs.front().number<<" ";
dogs.pop();
} else if (way == 0 && !cats.empty() && dogs.empty()){
cout<<cats.front().number<<" ";
cats.pop();
} else if (way == 1 && !dogs.empty()){
cout<<dogs.front().number<<" ";
dogs.pop();
} else if (way == -1 && !cats.empty()){
cout<<cats.front().number<<" ";
cats.pop();
}
}
}
return 0;
}
5.3 栈
5.3.1 逆序输出
#include<iostream>
#include<stack>
using namespace std;
int main(){
stack<int> sequence;
int n;//输入元素的个数
while(cin>>n){
for(int i = 0; i < n; i++){
long long number;
cin>>number;
sequence.push(number);
}
while(!sequence.empty()){
cout<<sequence.top()<<" ";
sequence.pop();
}
cout<<endl;
}
return 0;
}
5.3.2 括号匹配
#include<iostream>
#include<stack>
using namespace std;
int main(){
/*
括号匹配
给定一个字符串,判断该字符串中的括号是否可以匹配
如果左括号不匹配,在相应的位置输出?,右括号不匹配,在相应的位置输出#
其他位置输出空格
*/
string input, output;
stack<int> brackets;
cin>>input;
output = string(input.size(), ' ');
int index = 0;
while(index < input.size()){
if(input[index] == '('){
//左括号入栈
brackets.push(index);
index++;
} else if(input[index] == ')'){
//如果栈中有元素,则匹配,否则说明该右括号无法匹配,输出#
if (!brackets.empty()){
brackets.pop();
index++;
} else {
output[index] = '#';
index++;
}
} else{
//遇到字符,不做任何处理
index++;
}
}
//扫描一遍字符串后,如果栈非空,说明存在未匹配的左括号
while(!brackets.empty()){
output[brackets.top()] = '?';
brackets.pop();
}
cout<<output<<endl;
return 0;
}
5.3.3 简单计算器(表达式求值)
#include<iostream>
#include<stack>
using namespace std;
stack<double> numbers;
stack<char> operations;
double getNumber(string str, int &index) {
double number = 0;
while (isdigit(str[index])) {
number *= 10;
number += str[index] - '0';
index++;
}
return number;
}
int priority(char op) {
if (op == '#') {
return 0;
} else if (op == '$') {
return 1;
} else if (op == '+' || op == '-') {
return 2;
} else {
return 3;
}
}
double compute(double x, char op, double y) {
if (op == '+') {
return x + y;
} else if (op == '-') {
return x - y;
} else if (op == '*') {
return x * y;
} else {
return x / y;
}
}
int main(){
string str;
while (getline(cin, str)) {
if (str == "0") {
break;
}
operations.push('#');
str += '$';
int i = 0;
while (i < str.length()) {
//数字进入数字栈
if (str[i] == ' ') {
i++;
} else if (isdigit(str[i])) {
double number = getNumber(str, i);
numbers.push(number);
} else {
if (priority(str[i]) > priority(operations.top())) {
operations.push(str[i]);
i++;
} else {
double y = numbers.top();
numbers.pop();
double x = numbers.top();
numbers.pop();
char op = operations.top();
operations.pop();
//answer += compute(x, op, y);
numbers.push(compute(x, op, y));
}
}
}
cout.precision(2);
cout.setf(ios::fixed);
cout<<numbers.top()<<endl;
}
return 0;
}
六、 数学问题
6.1 进制转换
6.1.1 10进制转换为N进制
#include<iostream>
#include<stack>
using namespace std;
char Int2Char(int target){
if (target < 10) {
//如果数字小于10,则转换为相应的字符
return target + '0';
} else {
//如果数字大于10,则转换为相应的大写字母,如10->A
return target - 10 + 'A';
}
}
void ConvertT2N(int number, int n){
//将10进制转换为N进制
stack<char> answer;
if (number == 0) {
//如果number = 0,直接输出0
cout<<'0'<<endl;
} else if (number < 0) {
number *= -1;
while (number != 0) {
answer.push(Int2Char(number % n));
number /= n;
}
answer.push('-');
} else {
while (number != 0) {
answer.push(Int2Char(number % n));
number /= n;
}
}
//输出转换结果
while(!answer.empty()){
cout<<answer.top();
answer.pop();
}
cout<<endl;
}
int main(){
int number, n;
cin>>number>>n;
ConvertT2N(number, n);
return 0;
}
6.1.2 M进制转换为10进制
#include<iostream>
#include<string>
using namespace std;
int Char2Int(char c){
if (c >= '0' && c <= '9'){
return c - '0';
} else {
return c - 'A' + 10;
}
}
void ConvertM2T(string str, int m){
int number = 0;
for(int i = 0; i < str.size(); i++){
number *= m;
number += Char2Int(str[i]);
}
cout<<number<<endl;
}
int main(){
string str;
int m;
cin>>str>>m;
ConvertM2T(str, m);
return 0;
}
6.1.3 M进制转换为N进制
#include<iostream>
#include<string>
#include<stack>
using namespace std;
int Char2Int(char c){
if (c >= '0' && c <= '9'){
return c - '0';
} else {
return c - 'A' + 10;
}
}
char Int2Char(int target){
if (target < 10){
return target + '0';
} else {
return target - 10 + 'A';
}
}
long long ConvertM2T(string str, int m){
long long number = 0;
for(int i = 0; i < str.size(); i++){
number *= m;
number += Char2Int(str[i]);
}
return number;
}
void ConvertT2N(long long number, int n){
stack<char> answer;
if (number == 0) {
cout<<'0'<<endl;
} else {
while (number != 0) {
answer.push(Int2Char(number % n));
number /= n;
}
}
while (!answer.empty()){
cout<<answer.top();
answer.pop();
}
cout<<endl;
}
int main(){
string str;
int m, n;//输入M进制,输出N进制
cin>>m>>n;
cin>>str;
long long number = ConvertM2T(str, m);//M进制转换为10进制
//cout<<number;
ConvertT2N(number, n);//10进制转换为N进制
return 0;
}
6.2 最大公约数和最小公倍数
6.2.1 最大公约数
递归
#include<iostream>
using namespace std;
int GCD(int a, int b){
if (b == 0) {
//递归边界
return a;
} else {
return GCD(b, a % b);
}
}
int main(){
int a, b;
while(cin>>a>>b){
cout<<GCD(a, b)<<endl;
}
return 0;
}
循环
#include<iostream>
using namespace std;
int getAnswer(int x, int y) {
while (x % y != 0) {
int z = x % y;
x = y;
y = z;
}
return y;
}
int main(){
int x, y;
while (cin>>x>>y) {
cout<<getAnswer(x, y)<<endl;
}
return 0;
}
6.2.2 最小公倍数
LCM(a, b) = (a * b) / GCD(a, b)
#include<iostream>
using namespace std;
int GCD(int a, int b){
if (b == 0) {
//递归边界
return a;
} else {
return GCD(b, a % b);
}
}
int main(){
int a, b;
while(cin>>a>>b){
cout<<(a * b) / GCD(a, b)<<endl;
}
return 0;
}
6.3 质数
6.3.1 质数判别
#include<iostream>
#include<cmath>
using namespace std;
bool isPrimeNumber(int a) {
if (a < 2){
return false;
} else {
for (int i = 2; i <= pow(a, 0.5); i++) {
if (a % i == 0){
return false;
}
}
}
return true;
}
int main(){
int a;
while(cin>>a){
if (isPrimeNumber(a)) {
cout<<"yes"<<endl;
} else {
cout<<"no"<<endl;
}
}
return 0;
}
6.3.2 第k个质数
#include<iostream>
#include<vector>
using namespace std;
const int MAXN = 1e5 + 10;
vector<int> prime;
bool isPrime[MAXN];
void Initial() {
fill(isPrime, isPrime + MAXN, true);
isPrime[0] = false;
isPrime[1] = false;
for (int i = 2; i < MAXN; i++) {
if (!isPrime[i]) {
continue;
} else {
prime.push_back(i);
for (int j = i * 2; j < MAXN; j += i) {
isPrime[j] = false;
}
}
}
}
int main(){
Initial();
int k;
while(cin>>k){
cout<<prime[k-1]<<endl;
}
return 0;
}
6.3.3 质因数的个数
#include<iostream>
#include<vector>
using namespace std;
const int MAXN = 4e4;
vector<int> prime;
bool isPrime[MAXN];
void Initial() {
fill(isPrime, isPrime + MAXN, true);
isPrime[0] = false;
isPrime[1] = false;
for (int i = 2; i < MAXN; i++) {
if (!isPrime[i]) {
continue;
} else {
prime.push_back(i);
for (int j = i * 2; j < MAXN; j += i) {
isPrime[j] = false;
}
}
}
}
int getAnswer(int n) {
int answer = 0;
for (int i = 0; i < prime.size(); i++) {
while (n % prime[i] == 0) {
//prime[i]为质因数
answer++;
n /= prime[i];
}
}
if (n > 1) {
//该整数有一个大于根号n的质因子
//如600154635 = 3 * 5 * 40010309
answer += 1;
}
return answer;
}
int main(){
Initial();
int k;
while(cin>>k){
cout<<getAnswer(k)<<endl;
}
return 0;
}
6.3.4 约数个数
#include<iostream>
#include<vector>
using namespace std;
const int MAXN = 4e4;
vector<int> prime;
bool isPrime[MAXN];
void Initial() {
fill(isPrime, isPrime + MAXN, true);
isPrime[0] = false;
isPrime[1] = false;
for (int i = 2; i < MAXN; i++) {
if (!isPrime[i]) {
continue;
} else {
prime.push_back(i);
for (int j = i * 2; j < MAXN; j += i) {
isPrime[j] = false;
}
}
}
}
int getAnswer(int n) {
int answer = 1;
int e[prime.size()];
fill(e, e + prime.size(), 0);
for (int i = 0; i < prime.size(); i++) {
while (n % prime[i] == 0) {
//prime[i]为质因数
e[i]++;
n /= prime[i];
}
answer *= e[i] + 1;
}
if (n > 1) {
//该整数有一个大于根号n的质因子
//如600154635 = 3 * 5 * 40010309
answer *= 2;
}
return answer;
}
int main(){
Initial();
int k;
cin>>k;
while(k--){
int n;
cin>>n;
cout<<getAnswer(n)<<endl;
}
return 0;
}
6.4 快速幂
6.4.1 人见人爱A^B
#include<iostream>
using namespace std;
int QuickPower(int a, int b) {
int answer = 1;
/*
任何一个十进制整数都可以转换为2进制,如29=11101
所以3^29 = 3^1 * 3^4 * 3^8 * 3^16
可以通过这种方式求快速幂
*/
while (b != 0) {
if(b % 2 == 1) {
//对应的2进制位为1,则answer*a
answer *= a;
answer %= 1000;
}
//每次操作之后,b右移一位,a升幂
b /= 2;
a *= a;
a %= 1000;
}
return answer;
}
int main(){
int a, b;
while (cin>>a>>b) {
if (a == 0 && b == 0) {
break;
}
cout<<QuickPower(a, b)<<endl;
}
return 0;
}
6.5 矩阵
6.5.1 矩阵相加
#include<iostream>
using namespace std;
const int MAXN = 100;
//定义矩阵
struct Matrix{
int row, column;
int matrix[MAXN][MAXN];
Matrix(int r, int c) : row(r), column(c) {}
};
void inputMatrix(Matrix &x){
for (int i = 0; i < x.row; i++){
for (int j = 0; j < x.column; j++) {
cin>>x.matrix[i][j];
}
}
}
void outputMatrix(Matrix x){
for (int i = 0; i < x.row; i++) {
for (int j = 0; j < x.column; j++) {
if (j == 0) {
cout<<x.matrix[i][j];
} else {
cout<<" "<<x.matrix[i][j];
}
}
cout<<endl;
}
}
Matrix addMatrix(Matrix x, Matrix y) {
Matrix result = Matrix(x.row, x.column);
for (int i = 0; i < x.row; i++) {
for (int j = 0; j < x.column; j++){
result.matrix[i][j] = x.matrix[i][j] + y.matrix[i][j];
}
}
return result;
}
int main(){
Matrix x = Matrix(2, 2);
Matrix y = Matrix(2, 2);
inputMatrix(x);
inputMatrix(y);
outputMatrix(addMatrix(x, y));
return 0;
}
6.5.2 矩阵相乘
#include<iostream>
using namespace std;
const int MAXN = 100;
//定义矩阵
struct Matrix{
int row, column;
int matrix[MAXN][MAXN];
Matrix(int r, int c) : row(r), column(c) {}
};
void inputMatrix(Matrix &x){
for (int i = 0; i < x.row; i++){
for (int j = 0; j < x.column; j++) {
cin>>x.matrix[i][j];
}
}
}
void outputMatrix(Matrix x){
for (int i = 0; i < x.row; i++) {
for (int j = 0; j < x.column; j++) {
if (j == 0) {
cout<<x.matrix[i][j];
} else {
cout<<" "<<x.matrix[i][j];
}
}
cout<<endl;
}
}
Matrix multiplyMatrix(Matrix x, Matrix y) {
Matrix result = Matrix(x.row, y.column);
for (int i = 0; i < x.row; i++) {
for (int j = 0; j < y.column; j++){
result.matrix[i][j] = 0;
for (int k = 0; k < x.column; k++) {
result.matrix[i][j] += x.matrix[i][k] * y.matrix[k][j];
}
}
}
return result;
}
int main(){
Matrix x = Matrix(2, 3);
Matrix y = Matrix(3, 2);
inputMatrix(x);
inputMatrix(y);
outputMatrix(multiplyMatrix(x, y));
return 0;
}
6.5.3 矩阵转置
#include<iostream>
using namespace std;
const int MAXN = 100;
//定义矩阵
struct Matrix{
int row, column;
int matrix[MAXN][MAXN];
Matrix(int r, int c) : row(r), column(c) {}
};
void inputMatrix(Matrix &x){
for (int i = 0; i < x.row; i++){
for (int j = 0; j < x.column; j++) {
cin>>x.matrix[i][j];
}
}
}
void outputMatrix(Matrix x){
for (int i = 0; i < x.row; i++) {
for (int j = 0; j < x.column; j++) {
if (j == 0) {
cout<<x.matrix[i][j];
} else {
cout<<" "<<x.matrix[i][j];
}
}
cout<<endl;
}
}
Matrix transMatrix(Matrix x) {
Matrix result = Matrix(x.column, x.row);
for (int i = 0; i < x.column; i++) {
for (int j = 0; j < x.row; j++){
result.matrix[i][j] = x.matrix[j][i];
}
}
return result;
}
int main(){
Matrix x = Matrix(2, 3);
inputMatrix(x);
outputMatrix(transMatrix(x));
return 0;
}
6.5.4 矩阵的幂
#include<iostream>
using namespace std;
const int MAXN = 100;
//定义矩阵
struct Matrix{
int row, column;
int matrix[MAXN][MAXN];
Matrix(int r, int c) : row(r), column(c) {}
};
void inputMatrix(Matrix &x){
for (int i = 0; i < x.row; i++){
for (int j = 0; j < x.column; j++) {
cin>>x.matrix[i][j];
}
}
}
void outputMatrix(Matrix x){
for (int i = 0; i < x.row; i++) {
for (int j = 0; j < x.column; j++) {
if (j == 0) {
cout<<x.matrix[i][j];
} else {
cout<<" "<<x.matrix[i][j];
}
}
cout<<endl;
}
}
Matrix multiplyMaxtrix(Matrix x, Matrix y) {
Matrix result = Matrix(x.row, y.column);
for (int i = 0; i < x.row; i++) {
for (int j = 0; j < y.column; j++) {
result.matrix[i][j] = 0;
for (int k = 0; k < x.column; k++) {
result.matrix[i][j] += x.matrix[i][k] * y.matrix[k][j];
}
}
}
return result;
}
Matrix powerMatrix(Matrix x, int k) {
Matrix result = Matrix(x.row, x.column);
for (int i = 0; i < x.row; i++) {
for (int j = 0; j < x.column; j++) {
if (i == j) {
result.matrix[i][j] = 1;
} else {
result.matrix[i][j] = 0;
}
}
}
while (k != 0) {
if (k % 2 == 1) {
result = multiplyMaxtrix(result, x);
}
k /= 2;
x = multiplyMaxtrix(x, x);
}
return result;
}
int main(){
int n, k;
while (cin>>n>>k) {
Matrix x = Matrix(n, n);
inputMatrix(x);
outputMatrix(powerMatrix(x, k));
}
return 0;
}
6.6 大整数运算
6.6.1 大整数加法
6.6.2 大整数减法
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 10100;
char s1[MAXN], s2[MAXN], s3[MAXN]; //输入的两个数,先以字符串的形式保存
int a[MAXN], b[MAXN], c[MAXN]; //将字符串转换为数字并保持到数组中
bool compare(char str1[], char str2[]) {
// 判断str1是否大于str2
if (strlen(str1) != strlen(str2)) {
return strlen(str1) > strlen(str2);
}
for (int i = 0; i < strlen(str1); i++) {
if (str1[i] != str2[i]) {
return str1[i] > str2[i];
}
}
return true;
}
int main(){
cin>>s1>>s2;
int flag;
if (!compare(s1, s2)) {
// s1小于s2,交换
flag = 1; // 结果为负数
strcpy(s3, s1);
strcpy(s1, s2);
strcpy(s2, s3);
}
int la = strlen(s1);
int lb = strlen(s2);
int lc = max(la, lb);
for (int i = 0; i < la; i++) {
a[la - i] = s1[i] - '0';
}
for (int i = 0; i < lb; i++) {
b[lb - i] = s2[i] - '0';
}
for (int i = 1; i <= lc; i++) {
if (a[i] < b[i]) {
a[i+1]--;
a[i] += 10;
}
c[i] = a[i] - b[i];
}
if (flag == 1) {
cout<<'-';
}
// 前面有多个0,只保留一个
while (c[lc] == 0 && lc > 1) {
lc--;
}
for (int i = lc; i > 0; i--) {
cout<<c[i];
}
return 0;
}
6.6.3 大整数乘法
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 10100;
char s1[MAXN], s2[MAXN], s3[MAXN]; //输入的两个数,先以字符串的形式保存
int a[MAXN], b[MAXN], c[MAXN]; //将字符串转换为数字并保持到数组中
int main(){
cin>>s1>>s2;
int la = strlen(s1);
int lb = strlen(s2);
int lc = la + lb;
for (int i = 0; i < la; i++) {
a[la - i] = s1[i] - '0';
}
for (int i = 0; i < lb; i++) {
b[lb - i] = s2[i] - '0';
}
for (int i = 1; i <= la; i++) {
for (int j = 1; j <= lb; j++) {
c[i+j-1] += a[i] * b[j];
}
}
for (int i = 1; i <= lc; i++) {
if (c[i] > 9) {
c[i+1] += c[i] / 10;
c[i] %= 10;
}
}
// 前面有多个0,只保留一个
while (c[lc] == 0 && lc > 1) {
lc--;
}
for (int i = lc; i > 0; i--) {
cout<<c[i];
}
return 0;
}
6.6.4 大整数除法(高精度除以低精度)
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 5010;
char s[MAXN]; //输入的两个数,先以字符串的形式保存
long long a[MAXN], c[MAXN], x; //将字符串转换为数字并保持到数组中
long long b;
int main(){
cin>>s>>b;
long long la = strlen(s);
for (int i = 1; i <= la; i++) {
a[i] = s[i-1] - '0';
}
for (int i = 1; i <= la; i++) {
c[i] = (x * 10 + a[i]) / b;
x = (x * 10 + a[i]) % b;
}
long long lc = 1;
while (c[lc] == 0 && lc < la) {
lc++;
}
for (int i = lc; i <= la; i++) {
cout<<c[i];
}
return 0;
}
6.6.5 大整数除法(高精度除以高精度)
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 300 + 10;
char s1[MAXN], s2[MAXN];
int la, lb, lc;
int a[MAXN], b[MAXN], c[MAXN], temp[MAXN];
int compare(int a[], int b[]) {
if (a[0] > b[0]) {
return 1;
}
if (a[0] < b[0]) {
return -1;
}
for (int i = a[0]; i > 0; i--) {
if (a[i] > b[i]) {
return 1;
}
if (a[i] < b[i]) {
return -1;
}
}
return 0;
}
void copyArr(int b[], int temp[], int k) {
for (int i = 1; i <= b[0]; i++) {
temp[i + k] = b[i];
}
temp[0] = b[0] + k;
}
void Minus(int a[], int b[]) {
for (int i = 1; i <= a[0]; i++) {
if (a[i] < b[i]) {
a[i + 1]--;
a[i] += 10;
}
a[i] = a[i] - b[i];
}
while (a[a[0]] == 0 && a[0] > 1) {
a[0]--;
}
}
int main(){
cin>>s1>>s2;
a[0] = strlen(s1);
b[0] = strlen(s2);
for (int i = 0; i < a[0]; i++) {
a[a[0] - i] = s1[i] - '0';
}
for (int i = 0; i < b[0]; i++) {
b[b[0] - i] = s2[i] - '0';
}
c[0] = a[0] - b[0] + 1;
for (int i = c[0]; i >= 1; i--) {
memset(temp, 0, sizeof(temp));
copyArr(b, temp, i-1);
while (compare(a, temp) >= 0) {
c[i]++;
Minus(a, temp);
}
}
while (c[c[0]] == 0 && c[0] > 0) {
c[0]--;
}
for (int i = c[0]; i > 0; i--) {
cout<<c[i];
}
cout<<endl;
for (int i = a[0]; i > 0; i--) {
cout<<a[i];
}
return 0;
}
七、贪心策略
7.1 简单贪心
7.1.1 FatMouse's Trade
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1000;
struct change{
double javabean;
double food;
};
bool Compare(change x, change y) {
return x.javabean / x.food > y.javabean / y.food;
}
int main(){
/*
老鼠准备了M磅的猫粮,准备和房间里的猫交换咖啡豆,一共有N间房间。
第i间房间有J[i]磅的咖啡豆,需要F[i]的猫粮交换,老鼠不一定交换一间房间的所有咖啡豆
它可以用F[i]*a%的猫粮交换J[i]*a%的咖啡豆,求它可以获得最大咖啡豆的数量
*/
/*
F[i]的猫粮可以换J[i]的咖啡豆,若使交换的咖啡豆最多,应该尽量使用较少的猫粮交换较多的咖啡豆
可以利用J[i] / F[i] 计算交换比例,比例最大的为当前最优解
*/
int m, n;
while (cin >> m >> n) {
if (m == -1 && n == -1) {
break;
}
double answer = 0;
change input[MAXN];
for (int i = 0; i < n; i++) {
cin>>input[i].javabean>>input[i].food;
}
sort(input, input + n, Compare);
for (int i = 0; i < n; i++) {
if (m >= input[i].food) {
m -= input[i].food;
answer += input[i].javabean;
} else {
answer += (m / input[i].food) * input[i].javabean;
m = 0;
break;
}
}
cout.precision(3);
cout.setf(ios::fixed);
cout<<answer<<endl;
}
return 0;
}
7.1.2 Senior's Gun
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100000+10;
long long guns[MAXN];
long long monsters[MAXN];
bool Compare(long long x, long long y) {
return x > y;
}
int main(){
/*
薛有n把枪,每把枪的攻击力为a[i]
一天,她遇到了m头怪兽,每头怪兽的防御力为b[j]
只要满足a[i]>=b[j],薛就可以用枪杀死一头怪兽,并且获得a[i]-b[j]的奖金
一把枪只能杀死一头怪兽,尝试获得最多奖金。
*/
/*
若想获得最多奖金,应该用攻击力最强的枪杀死防御力最低的怪兽
*/
int t;
cin>>t;
while(t--){
int n, m;
long long bonus = 0;
cin>>n>>m;
//输入n把枪的攻击力
for (int i = 0; i < n; i++) {
cin>>guns[i];
}
//输入m头怪兽的防御力
for (int j = 0; j < m; j++) {
cin>>monsters[j];
}
//对枪和怪兽排序,用攻击力最高的枪杀死防御力最低的怪兽
sort(guns, guns + n, Compare);
sort(monsters, monsters + m);
for (int i = 0; i < n; i++) {
//以下两种情况跳出循环
//i.当前攻击力最高的枪无法杀死怪兽
//ii.所有的怪兽都已经被杀死
if (guns[i] < monsters[i] || i == m) {
break;
} else {
bonus += guns[i] - monsters[i];
}
}
cout<<bonus<<endl;
}
return 0;
}
7.1.3 箱子打包
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + 10;
int boxes[MAXN];
int main(){
int n;//物品个数
int length;//箱子长度
cin>>n;
cin>>length;
for (int i = 0; i < n; i++) {
cin>>boxes[i];
}
sort(boxes, boxes + n);
int shorter = 0;
int longer = n - 1;
int number = 0;
while (shorter <= longer) {
//如果长度最小的物品和长度最大的物品可以装入箱子中,则同时装入这两个物品
//否则,只装入长度最大的物品
if (boxes[shorter] + boxes[longer] <= length) {
shorter++;
longer--;
} else {
longer--;
}
number++;
}
cout<<number<<endl;
return 0;
}
7.1.4 aggressive cow
题目要求求出任意两个隔间最大的最小距离,可以使用二分策略:
指定一个距离,该距离为最小距离和最大距离的中间值,如果该距离满足题目中的要求,即任意两个隔间的距离都大于此距离,则说明该距离符合要求,此时要扩大该距离,以求出最大的距离,否则缩小该距离
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + 10;
int arr[MAXN];
bool judge(int n, int c, int distance){
int current = arr[0]; //最近放的牛所在的位置
int number = 1; //当前已放入牛的数量
for (int i = 1; i < n; i++) {
//如果把牛放在当前位置后,与前一个位置的距离大于等于指定的距离,则可以放入
if (arr[i] - current >= distance) {
current = arr[i];
number++;
}
//如果已放入的牛的数量等于c,则说明该距离满足要求
if (number == c) {
return true;
}
}
return false;
}
int main(){
//n:barn的数量,c:cow的数量
int n, c;
while (cin>>n>>c) {
for (int i = 0; i < n; i++) {
cin>>arr[i];
}
sort(arr, arr + n);
int left = 1; //两个barn之间的最小距离
int right = arr[n-1] - arr[0]; //两个barn之间的最大距离
while (left <= right) {
int middle = left + (right - left) / 2;
if (judge(n, c, middle)) {
//中间的距离满足要求,尝试将距离扩大
left = middle + 1;
} else {
//中间的距离不满足要求,尝试将距离缩小
right = middle - 1;
}
}
cout<<right<<endl;
}
return 0;
}
7.1.5 Drying
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 1e5 + 10;
int water[MAXN];
bool judge(int n, int k, int time) {
int sum = 0; //选择时间最长的送入烘干机
for (int i = 0; i < n; i++) {
//如果water[i] <= time,说明这件衣服可以在规定时间内自然晒干
//否则,需要送入烘干机,看是否可以在规定时间内烘干
if (water[i] > time) {
//当前衣服的含水量大于time,送入烘干机
sum += ceil((water[i] - time) * 1.0 / (k - 1));
}
if (sum > time) {
return false;
}
}
return true;
}
int main(){
int n; //衣服的数量
cin>>n;
for (int i = 0; i < n; i++) {
cin>>water[i]; //每件衣服的含水量
}
sort(water, water + n);
int k; //烘干机一分钟能够减少的含水量
cin>>k;
if (k == 1) {
//烘干机的速度与自然晒干的速度相同
cout<<water[n-1]<<endl;
} else {
//采用二分策略
int left = 1;
int right = water[n-1];
while (left <= right) {
int middle = left + (right - left) / 2;
if (judge(n, k, middle)) {
//当前时间可以烘干所有衣服,尝试减少时间
right = middle - 1;
} else {
//当前时间无法烘干所有衣服,尝试延长时间
left = middle + 1;
}
}
cout<<left<<endl;
}
return 0;
}
7.2 区间贪心
07.2.1 今年暑假不AC
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 100 + 10;
struct Program{
int starttime;
int endtime;
};
bool compare(Program a, Program b) {
return a.endtime < b.endtime;
}
Program programs[MAXN];
int main(){
int n;
while (cin>>n) {
if (n == 0) {
break;
}
int number = 1; //可以观看的节目数量
for (int i = 0; i < n; i++) {
cin>>programs[i].starttime>>programs[i].endtime;
}
//按照结束时间对每个节目进行排序
sort(programs, programs + n, compare);
//最近看完的节目的结束时间
int current = programs[0].endtime;
for (int i = 1; i < n; i++) {
//存在开始时间大于等于current的节目,则观看,并更新current
if (programs[i].starttime >= current) {
current = programs[i].endtime;
number++;
}
}
cout<<number<<endl;
}
return 0;
}
7.2.2 Radar Installation
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 1000 + 10;
struct Interval{
double left; //区间左端
double right; //区间右端
};
Interval arr[MAXN];
bool Compare(Interval a, Interval b) {
return a.left < b.left;
}
int main(){
int n, d; //n是岛屿的数目,d是雷达的探测半径
int caseNumber = 0;
while(cin>>n>>d){
if (n == 0 && d == 0) {
break;
}
bool flag = true;
for (int i = 0; i < n; i++) {
int x, y;//岛屿的坐标
cin>>x>>y;
if (y > d) {
//存在某个岛屿,其纵坐标大于雷达探测的半径,该岛屿不在探测范围内
flag = false;
} else {
//若雷达可以探测到该岛屿(x,y),则探测器应该安装在(x-r, x+r)之间,
//其中r=sqrt(d*d - y*y)
arr[i].left = x - sqrt(d * d - 1.0 * y * y);
arr[i].right = x + sqrt(d * d - 1.0 * y * y);
}
}
if (!flag) {
cout<<"Case "<<++caseNumber<<": "<<"-1"<<endl;
} else {
//对安装雷达的区间排序,排序规则为按照区间左端从小到大排序
sort(arr, arr + n, Compare);
int radar = 1;
//最新安装的雷达的位置
double current = arr[0].right;
for(int i = 1; i < n; i++) {
if (arr[i].left > current) {
//如果当前区间的左端大于前一个安装区间的右端,说明前一个安装的雷达无法
//探测到该位置,需要安装一个新的雷达,并更改current
current = arr[i].right;
radar++;
} else {
current = min(current, arr[i].right);
}
}
cout<<"Case "<<++caseNumber<<": "<<radar<<endl;
}
}
return 0;
}
八、 递归与分治
8.1 递归
8.1.1 汉诺塔1
8.1.2 全排列
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 10;
bool visited[MAXN]; //记录这个位置上的字母是否已经访问过
char sequence[MAXN]; //将访问过的字母加入字符串中
void getPermutation(string str, int depth){
if (depth == str.length()) {
//如果当前depth等于字符串长度,输出已访问的字符
for (int i = 0; i < str.length(); i++) {
cout<<sequence[i];
}
cout<<endl;
} else {
for (int i = 0; i < str.length(); i++) {
if (!visited[i]) {
visited[i] = true;
sequence[depth] = str[i];
getPermutation(str, depth + 1);
visited[i] = false;
}
}
}
}
int main(){
string str;
while (cin>>str) {
sort(str.begin(), str.end());
getPermutation(str, 0);
cout<<endl;
}
return 0;
}
8.2 分治
8.2.1 二叉树
#include<iostream>
using namespace std;
const int MAXN = 1e9 + 10;
int getNodeNumbers(int m, int n) {
//m为所求结点的子树中包含的结点个数
//n为二叉树中结点的个数
if (m > n) {
return 0;
} else {
// 对于结点m,其左孩子和右孩子分别为2m和2m+1
// 求以结点m为根结点的子树的结点的个数,可以转化为求以其左右孩子为根结点...
return getNodeNumbers(2 * m, n) + getNodeNumbers(2 * m + 1, n) + 1;
}
}
int main(){
int m, n;
while (cin>>m>>n) {
if (m == 0 && n == 0) {
break;
}
cout<<getNodeNumbers(m, n)<<endl;
}
return 0;
}
九、 搜索
9.1 广度优先搜索BFS
9.1.1 Catch that cow
#include<iostream>
#include<queue>
using namespace std;
const int MAXN = 1e5 + 10;
bool visited[MAXN]; //记录是否已经访问过某位置
struct Status{
//记录当前状态(所处位置,已耗费时间)
int position;
int time;
Status(int p, int t) : position(p), time(t){}
};
int BFS(int n, int k) {
// n为农夫当前位置 ; k为牛的位置
queue<Status> myQ;
// 定义当前位置以及耗费时间
visited[n] = true;
// 起始位置入队
myQ.push(Status(n, 0));
while (!myQ.empty()) {
Status current = myQ.front();
if (current.position == k) {
// 农夫已经遇到牛,结束BFS
return current.time;
} else {
// 当前队首不是目标状态,出队
myQ.pop();
for (int i = 0; i < 3; i++) {
// 每个状态后有三种状态选择
Status next = current;
if (i == 0) {
next.position += 1;
} else if (i == 1) {
next.position -= 1;
} else {
next.position *= 2;
}
if (next.position < 0 || next.position > 1e5 || visited[next.position]){
continue;
}
next.time += 1;
myQ.push(next);
visited[next.position] = true;
}
}
}
}
int main(){
int n, k;
cin>>n>>k;
cout<<BFS(n, k)<<endl;
return 0;
}
9.1.2 Find the multiple
#include<iostream>
#include<queue>
using namespace std;
long long BFS(int n) {
//找到一个数m,使得m = n*k,且m仅由0和1组成
/*
考虑以下方法:
初始状态仅有一个数字1,其转移状态为10或11
一般的,对于一个数字number,其转移状态为number*10或number*10+1
使用广度优先搜索,逐个判断队头数字number是否满足number%n=0,若满足,则返回
*/
queue<long long> number01;
number01.push(1);
while (!number01.empty()) {
long long current = number01.front();
number01.pop();
if (current % n == 0) {
return current;
} else {
number01.push(current * 10);
number01.push(current * 10 + 1);
}
}
}
int main(){
int n;
while (cin>>n) {
if (n == 0) {
break;
}
cout<<BFS(n)<<endl;
}
return 0;
}
9.2 深度优先搜索DFS
9.2.1 A knight's journey
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 30;
bool visited[MAXN][MAXN];
int direction[8][2] = { {-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-2, 1}, {2, 1}, {-1, 2}, {1, 2} };
bool DFS(int x, int y, int step, string answer, int p, int q) {
if (step == p * q) {
cout<<answer<<endl<<endl;
return true;
} else {
for (int i = 0; i < 8; i++) {
int nx = x + direction[i][0];
int ny = y + direction[i][1];
//判断nx和ny是否合法
if (nx < 0 || nx >=p || ny < 0 || ny >= q || visited[nx][ny]) {
continue;
}
visited[nx][ny] = true;
answer += ny + 'A';
answer += nx + '1';
if (DFS(nx, ny, step + 1, answer, p, q)) {
return true;
}
visited[nx][ny] = false;
}
}
return false;
}
int main(){
int n;
cin>>n;
int caseNumber = 0;
while (n--) {
int p, q;
cin>>p>>q;
memset(visited, false, sizeof(visited));
visited[0][0] = true;
cout<<"Scenario #"<<++caseNumber<<":"<<endl;
if (DFS(0, 0, 1, "A1", p, q)) {
continue;
} else {
cout<<"impossible"<<endl<<endl;
}
}
return 0;
}
9.2.2 Square
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 25;
bool visited[MAXN];
int sticks[MAXN];
bool Compare(int x, int y) {
return x > y;
}
bool DFS(int m, int sum, int number, int side) {
if (number == 3) {
return true;
} else {
for (int i = 0; i < m; i++) {
if (sum + sticks[i] > side || visited[i]) {
continue;
}
visited[i] = true;
if (sum + sticks[i] == side) {
if (DFS(m, 0, number+1, side)) {
return true;
}
} else {
if (DFS(m, sum + sticks[i], number, side)) {
return true;
}
}
visited[i] = false;
}
}
return false;
}
int main(){
int n;
cin>>n;
while (n--) {
int m;
cin>>m;
int length = 0;
for (int i = 0; i < m; i++) {
cin>>sticks[i];
length += sticks[i];
}
int side = length / 4;
if (length % 4 != 0) {
//不能构成正方形的四条边
cout<<"no"<<endl;
continue;
}
sort(sticks, sticks + m, Compare);
if (sticks[0] > side) {
cout<<"no"<<endl;
continue;
}
if (DFS(m, 0, 0, side)) {
cout<<"yes"<<endl;
} else {
cout<<"no"<<endl;
}
}
return 0;
}
减枝处理
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 25;
bool visited[MAXN];
int sticks[MAXN];
bool Compare(int x, int y) {
return x > y;
}
bool DFS(int m, int sum, int number, int p, int side) {
if (number == 3) {
return true;
} else {
int failSample = 0;
for (int i = p; i < m; i++) {
if (sum + sticks[i] > side || visited[i] || sticks[i] == failSample) {
continue;
}
visited[i] = true;
if (sum + sticks[i] == side) {
if (DFS(m, 0, number+1, 0, side)) {
return true;
} else {
failSample = sticks[i];
}
} else {
if (DFS(m, sum + sticks[i], number, i + 1, side)) {
return true;
} else {
failSample = sticks[i];
}
}
visited[i] = false;
}
}
return false;
}
int main(){
int n;
cin>>n;
while (n--) {
int m;
cin>>m;
int length = 0;
for (int i = 0; i < m; i++) {
cin>>sticks[i];
length += sticks[i];
}
int side = length / 4;
if (length % 4 != 0) {
//不能构成正方形的四条边
cout<<"no"<<endl;
continue;
}
sort(sticks, sticks + m, Compare);
if (sticks[0] > side) {
cout<<"no"<<endl;
continue;
}
memset(visited, false, sizeof(visited));
if (DFS(m, 0, 0, 0, side)) {
cout<<"yes"<<endl;
} else {
cout<<"no"<<endl;
}
}
return 0;
}
十、 非线性数据结构
10.1 二叉树
10.1.1 二叉树遍历
#include<iostream>
#include<string>
using namespace std;
struct treeNode{
char data;
treeNode* leftChild;
treeNode* rightChild;
treeNode(char c) : data(c), leftChild(nullptr), rightChild(nullptr) {}
};
treeNode* buildTree(string preOrder, string inOrder) {
if (preOrder.size() == 0) {
return nullptr;
}
char c = preOrder[0];
int position = inOrder.find(c);
treeNode* root = new treeNode(c);
root->leftChild = buildTree(preOrder.substr(1, position), inOrder.substr(0, position));
root->rightChild = buildTree(preOrder.substr(position+1), inOrder.substr(position+1));
return root;
}
void postOrder(treeNode* root){
if (root == nullptr) {
return;
}
postOrder(root->leftChild);
postOrder(root->rightChild);
cout<<root->data;
}
int main(){
string str1, str2;
while(cin>>str1>>str2) {
treeNode* root = buildTree(str1, str2);
postOrder(root);
cout<<endl;
}
return 0;
}
10.1.2 二叉排序树
#include<iostream>
using namespace std;
struct treeNode{
int data;
treeNode* leftChild;
treeNode* rightChild;
treeNode(int n) : data(n), leftChild(nullptr), rightChild(nullptr) {}
};
treeNode* insertNode(treeNode* root, int data) {
if (root == nullptr) {
root = new treeNode(data);
} else if (data > root->data) {
root->rightChild = insertNode(root->rightChild, data);
} else if (data < root->data) {
root->leftChild = insertNode(root->leftChild, data);
}
return root;
}
void preOrder(treeNode* root) {
if (root == nullptr) {
return;
}
cout<<root->data<<" ";
preOrder(root->leftChild);
preOrder(root->rightChild);
}
void inOrder(treeNode* root) {
if (root == nullptr) {
return;
}
inOrder(root->leftChild);
cout<<root->data<<" ";
inOrder(root->rightChild);
}
void postOrder(treeNode* root) {
if (root == nullptr) {
return;
}
postOrder(root->leftChild);
postOrder(root->rightChild);
cout<<root->data<<" ";
}
int main(){
int n;
while (cin>>n){
treeNode* root = nullptr;
while (n--) {
int data;
cin>>data;
root = insertNode(root, data);
}
preOrder(root);
cout<<endl;
inOrder(root);
cout<<endl;
postOrder(root);
cout<<endl;
}
return 0;
}
10.2 优先队列
10.2.1 复数集合
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
struct Complex{
int real;
int imag;
Complex(int a, int b) : real(a), imag(b) {}
bool operator< (Complex c) const {
if (c.imag * c.imag + c.real * c.real == imag * imag + real * real) {
//模长相等,虚部较小者优先级高
return c.imag < imag;
} else {
return c.imag * c.imag + c.real * c.real > imag * imag + real * real;
}
}
};
int main(){
int n;
while (cin>>n) {
priority_queue<Complex> myQueue;
while (n--) {
string str;
cin>>str;
if (str == "Pop") {
if (myQueue.empty()) {
cout<<"empty"<<endl;
} else {
//弹出优先级最高的元素,并输出SIZE
Complex top = myQueue.top();
myQueue.pop();
cout<<top.real<<"+i"<<top.imag<<endl;
cout<<"SIZE = "<<myQueue.size()<<endl;
}
} else {
//插入元素
int a, b;
scanf("%d+i%d", &a, &b);
Complex c = Complex(a, b);
myQueue.push(c);
cout<<"SIZE = "<<myQueue.size()<<endl;
}
}
}
return 0;
}
10.2.2 哈夫曼树
#include<iostream>
#include<queue>
using namespace std;
int main(){
int n;
while (cin>>n) {
priority_queue<int, vector<int>, greater<int> > Huffman;
int answer = 0;
while (n--) {
int weight;
cin>>weight;
Huffman.push(weight);
}
while (Huffman.size() > 1) {
int a = Huffman.top();
Huffman.pop();
int b = Huffman.top();
Huffman.pop();
int c = a + b;
Huffman.push(c);
answer += c;
}
cout<<answer<<endl;
}
return 0;
}
10.3 散列表
10.3.1 查找学生信息
#include<iostream>
#include<unordered_map>
#include<string>
using namespace std;
int main(){
int n;
cin>>n;
unordered_map<string, string> students;
getchar();
while (n--) {
string info;
getline(cin, info);
int position = info.find(" ");
string key = info.substr(0, position);
students[key] = info;
}
int m;
cin>>m;
while (m--) {
string key;
cin>>key;
string answer;
unordered_map<string, string>::iterator it = students.find(key);
if (it != students.end()) {
cout<<it->second<<endl;
} else {
cout<<"No Answer!"<<endl;
}
}
return 0;
}
十一、 图论
11.1 并查集
11.1.1 连通图
#include<iostream>
using namespace std;
const int MAXN = 1000 + 10;
int father[MAXN];
int height[MAXN];
void Initial(int n){
for (int i = 1; i <= n; i++) {
//对每个结点初始化为一个集合
father[i] = i;
height[i] = 0;
}
}
int Find(int x) {
if (father[x] != x) {
//压缩路径
father[x] = Find(father[x]);
}
return father[x];
}
void Union(int x, int y){
int f1 = Find(x); //得到元素x所在的集合
int f2 = Find(y); //得到元素y所在的集合
if (f1 != f2) {
//进行合并操作,矮树加到高树上
if (height[x] > height[y]) {
father[y] = x;
} else if (height[x] < height[y]) {
father[x] = y;
} else {
//两个集合高度相同
father[x] = y;
height[y]++;
}
}
}
int main(){
int n, m; //n为顶点个数,m为边数
while (cin>>n>>m) {
if (n == 0 && m == 0) {
break;
}
Initial(n);
while (m--) {
int x, y;
cin>>x>>y;
Union(x, y);
}
int number = 0;
for (int i = 1; i <= n; i++) {
if (father[i] == i) {
number++;
}
}
if (number == 1 ) {
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}
return 0;
}
11.2 最小生成树
11.2.1 还是畅通工程
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100 + 10;
int father[MAXN];
int height[MAXN];
struct Edge{
int from;
int to;
int weight;
bool operator< (Edge e) const {
return weight < e.weight;
}
};
Edge edges[MAXN*(MAXN-1)/2];
void Initial(int n){
for (int i = 0; i <= n; i++) {
father[i] = i;
height[i] = 0;
}
}
int Find(int x) {
if (x != father[x]) {
father[x] = Find(father[x]);
}
return father[x];
}
void Union(int x, int y) {
int f1 = Find(x);
int f2 = Find(y);
if (f1 != f2) {
if (height[f1] > height[f2]) {
father[f2] = f1;
} else if (height[f1] < height[f2]) {
father[f1] = f2;
} else {
father[f1] = f2;
height[f2]++;
}
}
}
int Kruskal(int n, int m) {
Initial(n);
int sum = 0;
int selectedEdge = 0;
sort(edges, edges + m);
for (int i = 0; i < m; i++) {
if (Find(edges[i].from) != Find(edges[i].to)) {
Union(edges[i].from, edges[i].to);
sum += edges[i].weight;
selectedEdge++;
//cout<<edges[i].from<<edges[i].to<<endl;
if (selectedEdge == n-1) {
break;
}
}
}
return sum;
}
int main(){
int n;
while (cin>>n) {
if (n == 0) {
break;
}
int m = n*(n-1)/2;
for (int i = 0; i < m; i++) {
cin>>edges[i].from>>edges[i].to>>edges[i].weight;
}
cout<<Kruskal(n, m)<<endl;
}
return 0;
}
☆注意Union函数中需要新定义f1和f2存放父结点
void Union(int x, int y) {
int f1 = Find(x);
int f2 = Find(y);
if (f1 != f2) {
if (height[f1] > height[f2]) {
father[f2] = f1;
} else if (height[f1] < height[f2]) {
father[f1] = f2;
} else {
father[f1] = f2;
height[f2]++;
}
}
}
11.3 最短路径
11.3.1 畅通工程续
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int MAXN = 200 + 10;
const int INF = INT_MAX;
struct Edge{
int to;
int length;
Edge(int t, int l) : to(t), length(l) {}
};
struct Point{
int number; //点的编号
int distance; //起始点到该点的距离
Point(int n, int d) : number(n), distance(d) {}
bool operator< (Point p) const {
return distance < p.distance;
}
};
int dis[MAXN]; // 起始点到其他所有结点的距离
vector<Edge> graph[MAXN]; //邻接表
int Dijkstra(int start, int n) {
// 进行初始化操作
fill(dis, dis + n, INF);
dis[start] = 0;
priority_queue<Point> unSelectedPoint;
unSelectedPoint.push(Point(start, dis[start]));
while (!unSelectedPoint.empty()) {
int u = unSelectedPoint.top().number;
unSelectedPoint.pop();
for (int i = 0; i < graph[u].size(); i++) {
int v = graph[u][i].to;
int d = graph[u][i].length;
if (dis[u] + d < dis[v]) {
dis[v] = dis[u] + d;
unSelectedPoint.push(Point(v, dis[v]));
}
}
}
}
int main(){
int n, m; //n为顶点个数,m为路径信息
while (cin>>n>>m) {
memset(graph, 0, sizeof(graph));
while (m--) {
int from, to, length;
cin>>from>>to>>length;
graph[from].push_back(Edge(to, length));
graph[to].push_back(Edge(from, length));
}
int start;
int terminal;
cin>>start>>terminal;
Dijkstra(start, n);
if (dis[terminal] == INF) {
dis[terminal] = -1;
}
cout<<dis[terminal]<<endl;
}
return 0;
}
11.4 拓扑排序
11.4.1 确定比赛名次
#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 500 + 10;
vector<int> graph[MAXN]; //邻接表
int inDegree[MAXN]; //记录每个点的入度
vector<int> topologicialSort(int n) {
vector<int> topoSequence;
priority_queue<int, vector<int>, greater<int> > myQueue;
//先将入度为0的点存放到优先队列
for (int i = 1; i <= n; i++) {
if (inDegree[i] == 0) {
myQueue.push(i);
}
}
while (!myQueue.empty()) {
int u = myQueue.top();
myQueue.pop();
topoSequence.push_back(u);
// 删掉该顶点及其边,修改相连顶点的入度
for (int i = 0; i < graph[u].size(); i++) {
int v = graph[u][i];
inDegree[v]--;
if (inDegree[v] == 0) {
myQueue.push(v);
}
}
}
return topoSequence;
}
int main(){
int n, m;
while (cin>>n>>m) {
memset(graph, 0, sizeof(graph));
memset(inDegree, 0, sizeof(inDegree));
while (m--) {
int from, to;
cin>>from>>to;
graph[from].push_back(to);
inDegree[to]++;
}
vector<int> answer = topologicialSort(n);
for (int i = 0; i < answer.size(); i++) {
if (i == 0) {
cout<<answer[i];
} else {
cout<<" "<<answer[i];
}
}
cout<<endl;
}
return 0;
}
11.5 关键路径
11.5.1 Instrction Arrangement
给你n和m代表编号0 ~ n-1个任务(顶点),和m条关系(边),每条关系由X、Y、Z,代表想要完成Y必须先完成X并花费Z个时间、CPU可以同时完成多个任务处理,一次花费一个单位时间。问完成0 ~ n-1个任务需要多少时间。
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int MAXN = 1000 + 10;
struct Edge{
int to;
int length;
Edge(int t, int l) : to(t), length(l) {}
};
vector<Edge> graph[MAXN];
int ve[MAXN];
int vl[MAXN];
int inDegree[MAXN];
void criticalPath(int n) {
queue<int> myQueue;
for (int i = 0; i < n; i++) {
if (inDegree[i] == 0) {
ve[i] = 1;
myQueue.push(i);
}
}
while (!myQueue.empty()) {
int u = myQueue.front();
myQueue.pop();
for (int i = 0; i < graph[u].size(); i++) {
int v = graph[u][i].to;
int l = graph[u][i].length;
ve[v] = max(ve[v], ve[u] + l);
inDegree[v]--;
if (inDegree[v] == 0) {
myQueue.push(v);
}
}
}
}
int main(){
int n, m;
while (cin>>n>>m) {
memset(graph, 0, sizeof(graph));
memset(ve, 0, sizeof(ve));
memset(inDegree, 0, sizeof(inDegree));
while (m--) {
int from, to, length;
cin>>from>>to>>length;
graph[from].push_back(Edge(to, length));
inDegree[to]++;
}
criticalPath(n);
int answer = 0;
for (int i = 0; i < n; i++) {
answer = max(answer, ve[i]);
}
cout<<answer<<endl;
}
return 0;
}
十二、 动态规划
12.1 递推求解
12.1.1斐波那契数列(递推)
#include<iostream>
using namespace std;
const int MAXN = 100 + 10;
int f[MAXN];
int Fibonacci(int n) {
for (int i = 0; i <= n; i++) {
if (i == 0 || i == 1) {
f[i] = i;
} else {
f[i] = f[i-1] + f[i-2];
}
}
return f[n];
}
int main(){
int n;
cin>>n;
cout<<Fibonacci(n)<<endl;
return 0;
}
12.2 最大连续子序列和
12.2.1 最大序列和
#include<iostream>
using namespace std;
const int MAXN = 1e6 + 10;
const int INF = INT_MAX;
int f[MAXN];
int arr[MAXN];
void greatestSum(int n){
for (int i = 0; i < n; i++) {
//求出每个位置的最大序列和
/*
给定数列 -1 3 4 -8 6
对于数3,索引为1,其对应的最大序列和为max(3, f(1) + 3)
*/
if (i == 0) {
f[i] = arr[i];
} else {
f[i] = max(arr[i], arr[i] + f[i-1]);
}
}
}
int main(){
int n;
while (cin>>n) {
for (int i = 0; i < n; i++) {
cin>>arr[i];
}
greatestSum(n);
int answer = -INF;
for (int i = 0; i < n; i++) {
answer = max(answer, f[i]);
}
cout<<answer<<endl;
}
return 0;
}
12.3 最长递增子序列
12.3.1 Longest Ordered Subsequence
#include<iostream>
using namespace std;
const int MAXN = 1000 + 10;
int arr[MAXN];
int dp[MAXN];
void longestSequence(int n) {
for (int i = 0; i < n; i++) {
if (i == 0) {
//第一个数字的最长递增子序列长为1
dp[i] = 1;
} else {
dp[i] = 1; //初始化为1,如果可以形成递增子序列,再修改
for (int j = 0; j < i; j++) {
if (arr[j] < arr[i]) {
dp[i] = max(dp[i], dp[j]+1);
}
}
}
}
}
int main(){
int n;
cin>>n;
for (int i = 0; i < n; i++) {
cin>>arr[i];
}
longestSequence(n);
int answer = 0;
for (int i = 0; i < n; i++) {
answer = max(answer, dp[i]);
}
cout<<answer<<endl;
return 0;
}
12.4 最长公共子序列
12.4.1 Common subsequence
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1000 + 10;
char str1[MAXN];
char str2[MAXN];
int dp[MAXN][MAXN];
void commonSubsequence(int n, int m) {
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++) {
if (i == 0 || j == 0) {
dp[i][j] = 0;
} else {
if (str1[i] == str2[j]) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
}
}
int main(){
while (cin>>str1+1>>str2+1) {
int n = strlen(str1 + 1);
int m = strlen(str2 + 1);
commonSubsequence(n, m);
cout<<dp[n][m]<<endl;
/*
commonSubsequence(strlen(str1 + 1), strlen(str2 + 1));
int answer = 0;
for (int i = 0; i <= strlen(str1 + 1); i++) {
for (int j = 0; j <= strlen(str2 + 1); j++) {
answer = max(answer, dp[i][j]);
//cout<<dp[i][j]<<" ";
}
//cout<<endl;
}
cout<<answer<<endl;
*/
}
return 0;
}
12.5 背包问题
12.5.1 点菜问题(0-1背包)
#include<iostream>
using namespace std;
const int MAXN = 1000 + 10;
int weight[MAXN];
int value[MAXN];
int dp[MAXN][MAXN];
int main(){
int c, n;
while (cin>>c>>n) {
for (int i = 1; i <= n; i++) {
cin>>weight[i]>>value[i];
}
//dp数组初始化
for (int i = 0; i <= c; i++) {
dp[i][0] = 0;
}
for (int j = 0; j <= n; j++) {
dp[0][j] = 0;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= c; j++) {
if (j < weight[i]) {
//dp[i][j]代表前i件物品装入容量为j的背包里能获得的最大价值
dp[i][j] = dp[i-1][j];
} else {
dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i]);
}
}
}
cout<<dp[n][c]<<endl;
}
return 0;
}