Blue Bridge Cup pre-match review

pair usage:

Application scenario: mainly to combine two data into a set of data, the basic implementation is a structure, and member variables can be used directly

head File:#include <utility>

structure:pair<T1, T2> p1;//T1,T2为数据类型,p1为变量名

Access member variables:p1.first;p1.second;

简化:
typedef pair<string,string> Author
Author proust(“March”,“Proust”);

full array

DFS implementation

//index:当前一共搜索index个数
//n:全排列的总数
void DFS(int index, int n)
{
//搜索完 输出
if (index >= n)
{
	//vector C11输出方式
	for (int x : num)
		cout << x << " ";
	cout << endl;
	return;
}

for (int i = 1; i <= n; i++)
{
	//已经搜索过,退出进行下一个
	if (isUsed[i]) continue;
	num.push_back(i);
	isUsed[i] = true;
	DFS(index + 1, n);
	num.pop_back();
	isUsed[i] = false;
}
}

next_permutation implementation

//头文件:#include <algorithm>
do{
	Cout_Permutation(); //输出S
}while(next_permutation(s,s+3));//对S中前3个数全排列

String common functions

substr(begin,length)//从begin开始,复制长度为length的字符串
memset(m,'1',7);//对char数组赋值 头文件:<cstring>
cout<<"m的长度:"<<strlen(m)<<endl;
//strcmp若二者相等,则返回0 
if(!strcmp(s,m))
cout<<"Same"<<endl;
else 
cout<<"Different"<<endl;
//s连接到m上,但必须保证m的长度足够接收 
strcat(m,s);
cout<<"连接后m的长度"<<strlen(m)<<endl;
for(int i = 0;i<sizeof(m);i++)
{
	cout<<m[i]<<" ";
}
cout<<endl;
//将m复制给n,必须保证n空间足够,否则将造成数据丢失 
strcpy(n,m);
for(int i = 0;i<sizeof(n);i++)
{
	cout<<n[i]<<" ";
}
cout<<endl;
/*strstr函数会寻找参数二在参数中出现的位置,
并返回查找到字符串的位置之后的全部字符串。
当没有查找到符合的字符串时,strstr函数会返回 FALSE(布尔值)。*/
cout<<strstr(n,s);

Fill function fill()

//fill()函数参数:fill(first,last,val);
// first 为容器的首迭代器,last为容器的末迭代器,val为将要替换的值。
//实例:
int a[200];
fill(a, a+100, 1);
//memset(),则是将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值,即0 、1

vector common functions

//常用vector的函数 
void Verify_vector()
{
text.push_back(1);//末尾添加元素1 
text.insert(text.begin()+2,99);//第三个元素前插入99 
cout<<"插入一个数后Text的值:";
 Vector_Output();
 text.erase(text.begin()+2);//删除第3个元素
 cout<<"删除一个数后Text的值:";
 Vector_Output();
 text.pop_back();//移除尾部的数 
 cout<<"删除最后一个数后Text的值:";
 Vector_Output();
 reverse(text.begin(),text.end());//容器内部数据翻转 
 cout<<"翻转后Text的值:";
 Vector_Output();
 cout<<"输出第四个数:"<<text.at(3)<<endl; 
 cout<<"输出第一个数:"<<text.front()<<endl; 
 cout<<"输出最后一个数:"<<text.back()<<endl; 
 vector<int>::iterator it;
//lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,
//找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
  it = lower_bound(text.begin(),text.end(),8);
  cout<<*it;
 text.clear();//清空 
 
}

set collection

The underlying data structure of set is a variant of red-black tree, and insertion and deletion operations are faster than vector.

Multiset is similar to set, but each element value of set can only appear once, while the same value can appear multiple times in multiset. It can be repeated, which is very suitable in some scenarios

unordered_set represents an unsorted combination, the elements it contains are unique, the elements in unordered_set will not be automatically sorted, and its element values ​​cannot be directly modified.

The underlying data structure of unordered_set is a hash table, and insertion and lookup operations are faster than set. Where a hash table needs to be used, unordered_set can be used.

#include <iostream>
#include <set>	//包含set和multiset 
#include <vector>
using namespace std;

set <int> s1;
multiset <int> ms1;

int main()
{
//仅拿set举例
s1.size()  ;  //返回s1的大小
if(s1.empty()) //若s1为空则返回true,否则返回false。
s1.insert(2);    //将2插入s1中。s1中值为{2}。
if(ms1.empty())
ms1.insert(3);

vector<int> v={1,4,5,6};//C11方法,蓝桥杯中慎用
s1.insert(v.begin(), v.end());    //将区间内的数全都插入s1中。s1中值为{1,2,4,5,6};。
vector<int> e={1,4,4,5,5,6};//ms1中值为{1,2,4,4,5,5,6};。
ms1.insert(e.begin(), e.end());  
s1.erase(5);    //删除5。s1中值为{1,2,4,6}。
int a = ms1.erase(5);//在multiset中这种删除方法会删除所有这个值的元素,而不是删除一个,返回值为删除的个数。
cout<<a<<endl;

s1.find(4);    //查找元素4。若找到则返回该元素对应迭代器,找不到则返回s1.end()。

int b = s1.count(4);    //查找元素4的个数。对于set只会返回0或1,对于multiset则返回元素的个数,可以为多个
cout<<b<<endl;
int c = ms1.count(4);
cout<<c<<endl;
return 0;
 } 

The set parameter is a structure, and the < sign needs to be overloaded

`struct Pair
{
int x;
int y;
};
bool operator<(Pair x, Pair y)//对<运算符 重载 
{
 //按照想要的顺序,自定义运算符
 //类似:对插入set的结构体数组自定义排序
if (x.x < y.x)return true;
if (x.x == y.x&&x.y < y.y)return true;
return false;
}

map

头文件:#include <map>

The map definition method is: map<key,values> a;

The key corresponds to the values ​​one-to-one, and the corresponding values ​​can be found through the key. The key and values ​​can be of any type and are defined according to their own needs, for example:

map<string,int> s;

Of course, this definition is very long, we can rename it, and then the definition is simple:

typedef map<string,map> maps;
maps s;
//插入元素
// 定义一个map对象
map<int,string> mapStudent;
 
// 第一种 用insert函数插入pair
mapStudent.insert(pair<int, string>(000, "student_zero"));

// 第二种 用"array"方式插入
mapStudent[123] = "student_first";
mapStudent[456] = "student_second";

In fact, we mainly use the above two methods, but the above two methods are different. For the first method, if the key value exists, it cannot be inserted successfully, and for the second method, if the key exists, its original corresponding values ​​will be overwritten

find element

// find 返回迭代器指向当前查找元素的位置否则返回map::end()位置
iter = mapStudent.find(key);

delete

//迭代器刪除
iter = mapStudent.find(key);
mapStudent.erase(iter);
 
//用关键字刪除
int n = mapStudent.erase(key); //如果刪除了會返回1,否則返回0
 
//用迭代器范围刪除 : 把整个map清空
mapStudent.erase(mapStudent.begin(), mapStudent.end());
//等同于mapStudent.clear()

Priority queue (priority_queue)

The priority queue has all the characteristics of the queue, including the basic operation of the queue, but adds an internal sorting on this basis, which is essentially a heap implementation.

The basic operation is the same as the queue:

top Access the head element
empty Whether the queue is empty
size Return the number of elements in the queue
push Insert elements to the tail of the queue (and sort)
emplace Construct an element in place and insert it into the queue
pop Pop the head element
swap swap content

Definition: priority_queue<Type, Container, Functional>
Type is the data type, Container is the container type (Container must be a container implemented by an array, such as vector, deque, etc., but a list cannot be used. The default in STL is vector), and Functional is the way of comparison.

When you need to use a custom data type, you need to pass in these three parameters. When using a basic data type, you only need to pass in the data type. The default is the big top heap.

 //升序队列,小顶堆 小的先出队
priority_queue <int,vector<int>,greater<int> > q;
//降序队列,大顶堆
priority_queue <int,vector<int>,less<int> >q;
//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。
//其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)

E.g:

priority_queue<node> q;//优先队列定义方式 
//node是结构体,需要 **重定义 "<" 符合**
node temp(sx,sy,0);
q.push(temp); //插入
temp=q.top();//记录队顶 
q.pop();//队顶元素出队

Binary tree:

Definition of a binary tree:

typedef struct Node{
	int data;//权值
	Node* lchild,* rchild;//左右孩子
}Node;

Node* createNode(int data)//创建根节点,同时令左右节点为null
{
	Node* temp = (Node*)malloc(sizeof(Node));
	temp->data = data;
	temp->lchild = temp->rchild = NULL;
	return temp;
}

traversal of binary tree

//前序,中序,后序遍历
//均使用递归完成
//不同仅在于输出根节点的时间不同
void preorderTrav(Node* root)//递归实现先序遍历
{
if (root == NULL)
	return;
cout << root->data<<" ";
preorderTrav(root->lchild);
preorderTrav(root->rchild);
}
void inorderTrav(Node* root)//递归实现中序遍历
{
if (root == NULL) return;
inorderTrav(root->lchild);
cout << root->data<<" ";
inorderTrav(root->rchild);
}
void pastorderTrav(Node* root)//递归实现后序遍历
{
if (root == NULL) return;
pastorderTrav(root->lchild);
pastorderTrav(root->rchild);
cout << root->data << " ";

}

int getTreeHeight(Node* root)//分别遍历左右子树得到高度取最大值 
{
if (root == NULL) return 0;
int leftHeight = getTreeHeight(root->lchild);
int rightHeight = getTreeHeight(root->rchild);
return max(leftHeight, rightHeight) + 1;
}

Knowing the inorder and postorder, find the preorder

`void preorder(string inorder,string pastorder)
{

if(pastorder.length()==0)
return ; 
if(pastorder.length()==1)
{
	cout<<inorder[0];
	return ;
} 
//pastorder.length()-1:先序遍历的第一个数在后序遍历中的位置 
//寻找 先序遍历的第一个数在中序遍历的位置
int pos = inorder.find(pastorder[pastorder.length()-1]);
//输出该数 
cout<<pastorder[pastorder.length()-1];
// 拆分中序和后序,重新查找 
preorder(inorder.substr(0,pos),pastorder.substr(0,pos));
preorder(inorder.substr(pos+1,pastorder.length()-pos-1),pastorder.substr(pos,pastorder.length()-pos-1));	   	 	 	
} `

base conversion

Hexadecimal to decimal

for (int i = 0; arr[i]!='\0'; i++)         //最后一位是'\0',不用算进去
 {
     switch (arr[i])
     {
     case 'A': temp = 10; break;
     case 'B': temp = 11; break;
     case 'C': temp = 12; break;
     case 'D': temp = 13; break;
     case 'E': temp = 14; break;
     case 'F': temp = 15; break;
     default: temp = arr[i] - '0'; break;
     }
     sum = sum + temp * pow(16, n - 1- i);
 }

Convert any base to decimal C11

int a;//表示输入的进制 
char b[maxn]; //b表示输出的a进制数 
char *result;
cin>>a>>b;
long ret = strtol(b,&result,a);//转换为10进制 
cout<<ret; 

Convert decimal to arbitrary base C11

int a,b ; 
char result[maxn];
cin>>a>>b;
//a:待转换的数
//b:待转换的进制
//result:存放转换后的进制,必须为char型数组 
itoa(a,result,b);//转换为10进制 
printf("%s",result);

big data operation

int main()
{
cin>>n;
a.push_back(0);
a.push_back(1);//为了方便从1开始运算 
int temp;
for(int i = 1;i<=n;i++)
{
	//每一位都要和下一个数相乘,但是先不能考虑进位
	//避免进位的数据被下一个数相乘
	//例如69*3,先算3*9 = 27,需要进位,但是要先算3*6 = 18,
	//再用18+2 = 20;
	//最后考虑进位2;  
	for(int j = 1;j<=a.size()-1;j++)
	{
		a[j] = a[j]*i;
	}
	//考虑进位
	for(int j = 1;j<=a.size()-1;j++)
	{
		if(a[j]>=10)
		{
			temp = a[j]/10;
			a[j] = a[j]%10;
			if(j<a.size()-1)
			{
				a[j+1] = a[j+1]+temp;
			}
			//最高位仍需要进位,需要将进位放入vector中
			else if(j==a.size()-1)
			{
				a.push_back(temp);
			}
		}
	}
}
for(int i = a.size()-1;i>0;i--)
cout<<a[i];
return 0;
} 

When the amount of input data is variable

while (scanf("%d", &a[k++]) != EOF);//不定输入,Ctrl+Z结束输入 

dynamic programming

Determine the meaning of the dp array

In a one-dimensional dp array, dp[j] means: a backpack with a capacity of j, the value of the items carried can be up to dp[j].
The two-dimensional dp array dp[i][j], dp[i][j] means to take any item from the subscript [0-i] and put it into the backpack of capacity j, what is the maximum value of the sum

Determine the recursion formula

2D dp

It is derived from dp[i - 1][j], that is, the capacity of the backpack is j, and the maximum value of item i is not placed in it. At this time, dp[i][j] is dp[i - 1][j]
2. From dp [i - 1][j - weight[i]] is introduced, dp[i - 1][j - weight[i]] is the maximum value of item i when the backpack capacity is j - weight[i], then dp[i - 1][j - weight[i]] + value[i] (the value of item i), which is the maximum value obtained by placing item i in the backpack. The maximum value
of the two is dp[i][j]
, so recursion Formula: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

one-dimensional dp

When using the recursive formula of two-dimensional dp, dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i] ); Add and copy dp[i-1] to dp[i], you can get dp[i][j] = max(dp[i][j], dp[i[j - weight[i]] + value[i]);
This can be replaced by a one-dimensional array, so dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

initialization

2D dp

It can be seen from the state transition equation that i is derived from i-1, so when i is 0, it must be initialized.

dp[0][j], that is: i is 0, when storing the item number 0, the maximum value that can be stored in the backpack of each capacity .

code show as below:

// 倒叙遍历 

for (int j = bagWeight; j >= weight[0]; j--) { 
dp[0][j] = dp[0][j - weight[0]] + value[0]; // 初始化i为0时候的情况 

Two-dimensional dp cannot be initialized in positive order!

one-dimensional dp

dp[j] means: a backpack with a capacity of j, the maximum value of the items carried can be dp[j], then dp[0] should be 0, because the maximum value of the items carried by the backpack with a capacity of 0 is 0.

Then, except for the position of subscript 0, the dp array is initially 0. How many other subscripts should be initialized?

Take a look at the recursive formula: dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

The dp array must be the number with the largest value when deriving. If the value given by the title is all positive integers , then all non-0 subscripts can be initialized to 0. If the value given by the title is negative , then the non-0 subscript will be To be initialized to negative infinity .

In this way, the dp array can take the maximum value during the recursive formula process, rather than being overwritten by the initial value.

traverse

Two-dimensional dp positive order traversal first traverse the items

// weight数组的大小 就是物品个数
for(int i = 1; i < weight.size(); i++) { // 遍历物品
for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量 
if (j < weight[i]) dp[i][j] = dp[i - 1][j]; // 这个是为了展现dp数组里元素的变化
else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

}
}

One-dimensional dp backpack capacity flashback traversal! Iterate over items first

for(int i = 0; i < weight.size(); i++) { // 遍历物品
for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

}
}

01 Knapsack segmentation equal and subset

Question: Given a non-empty array containing only positive integers. Is it possible to split this array into two subsets such that the element sums of the two subsets are equal.

Idea: The item is a given array, and the capacity of the backpack is sum/2; the maximum capacity that the backpack can hold, whether it is just full

##01 Backpack Last Stone Weight

Question: There is a pile of stones, and the weight of each stone is a positive integer.

Each round, choose any two stones from them and smash them together. Suppose the weights of the stones are x and y, and x <= y. Then the possible outcomes of smashing are as follows:

If x == y, then both stones will be completely shattered;
if x != y, then the stone of weight x will be completely shattered, and the stone of weight y will have a new weight of yx.
In the end, at most one stone remains. Returns the smallest possible weight for this stone. Returns 0 if there are no stones left.

Ideas: Same as above, the item is a given stone, and the backpack capacity is sum/2; half as much as possible, and the final difference is the result

01 Knapsack combination problem

Question: Given an array of non-negative integers, a1, a2, …, an, and a target number, S. Now you have two symbols + and -. For any integer in the array, you can choose a sign from + or - to prepend.

Returns the number of methods that can make the final array and all sign-on for the target number S.

Idea: Suppose the sum of addition is x, then the sum corresponding to subtraction is sum - x.

So what we're asking for is x - (sum - x) = S

x = (S + sum) / 2 //backpack capacity

dp[j] means: there are dp[i] methods to fill up a bag with such a large volume as j (including j).

Filling the knapsack with capacity j - nums[i] without considering nums[i], there are methods in dp[j - nums[i]].

Then as long as you get nums[i], there are dp[j - nums[i]] ways to make up dp[j].

For example, nums[i] = 2: dp[3], if the capacity of the backpack is 3, there are dp[3] methods.

Then you only need to get a 2 (nums[i]), there is a dp[3] method to collect a backpack with a capacity of 3, and accordingly there are as many ways to collect a backpack with a capacity of 5.

Then you need to accumulate these methods, dp[i] += dp[j - nums[j]]

General formula for combination class: dp[j] += dp[j - nums[i]] (accumulation)

Initialization: dp[0] = 1, which is also well explained in theory. There is one way to fill a backpack with a capacity of 0, which is to load 0 items.

The values ​​corresponding to other subscripts of dp[j] should be initialized to 0. It can also be seen from the recursive formula that dp[j] must be guaranteed to be the initial value of 0 in order to be correctly derived from dp[j - nums[i]] .

01 Backpack Backpack has two dimensions

Find and return the size of the largest subset of strs with at most m 0s and n 1s.

A set x is a subset of a set y if all elements of x are also elements of y.

Example 1:

Input: strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
Output: 4

Idea: dp[i][j] can be derived from the string in the previous strs. The string in strs has zeroNum 0s and oneNum 1s.

dp[i][j] can then be dp[i - zeroNum][j - oneNum] + 1.

Then we take the maximum value of dp[i][j] during the traversal process.

So the recursive formula: dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1

initialized to 0

The traversal method remains unchanged, and it is still a flashback traversal

Number of complete backpack combinations

A complete backpack means that each item has an infinite number, so the backpack capacity is traversed from small to large, ensuring that each item can be traversed multiple times

Question: Given coins of different denominations and a total amount. Write a function to count the number of coin combinations that make up the total amount. Suppose there are infinite coins of each denomination.

Idea: Since the number of combinations is sought, the same amount in different orders is the same situation, you can use the previous formula for the number of combinations: dp[j] += dp[j - nums[i]]
Since the number of combinations is required, the order is not considered, So first traverse the items and then traverse the backpack. If it is the number of permutations, if the order needs to be considered, first traverse the backpack and then traverse the items.

The initialization is still dp[0] = 1!;

The above initialization is 0, all because the maximum value needs to be obtained, and the minimum value is required to be added, and it needs to be initialized to infinity.

Multipack

There are N items and a knapsack of capacity V. The i-th item has at most Mi pieces available, each costing a space of Ci and a value of Wi. Find which items to put into the backpack so that the sum of the space consumption of these items does not exceed the backpack capacity, and the sum of the value is the largest.

The multiple backpack is very similar to the 01 backpack, why is it similar to the 01 backpack?

Each item has at most Mi pieces available. Spreading the Mi pieces is actually a 01 backpack problem.

longest ascending subsequence

dynamic programming

According to the general rules of dynamic programming, if we want to know the longest ascending subsequence of a sequence a[n] of length n, we can use the longest ascending subsequence of the first (n-1) sequences, followed by the nth number For comparison, get the longest ascending subsequence of the first n numbers... and so on until the longest ascending subsequence of the first number is obtained, of course LIS(1) = 1;

Let's start the five steps of dynamic programming:

Determine the dp array and its meaning
In the longest ascending subsequence, dp[i] represents the longest ascending subsequence ending with a[i]

Initialize
dp[i] = 1 ; it means that there is only a[i] in the sequence. Of course, this situation is generally the smallest, so initialize

Determine the recursion formula

Since dp[i] represents the longest ascending subsequence ending with a[i], it must be found before i, find a sequence smaller than a[i], and add a[i], then
dp[i] = dp[j]+1;(0<j<i), but what if there is no sequence less than a[i] in front? Then only a[i] can be selected. At this time, the length is 1, which is the dp[i] we initialized at the beginning;

Finally get dp[i] = max(dp[j]+1,dp[i]) (0<j<i) and require a[j]<a[i]

start traversing

for(int i=1; i<=n; i++)
   for(int j=1; j<i; j++)
 if(a[j] < a[i])
   f[i] = max(f[i], f[j]+1)

result

The result is to find the maximum value in the obtained dp array, remember, this is different from general dynamic programming

dp[n] is not necessarily the maximum value we are looking for. This can be seen from our dp array definition, dp[i] is not
the longest ascending subsequence of the first i, but contains a[i], with a[i] is the longest ascending subsequence at the end,
so the dp array is finally traversed

for(int i = 0;i<dp.size();i++)
{
	if(max<dp[i])
	max = dp[i]
}

The final max is the result we want! ! !

Greedy + Dichotomous

principle

For a sequence a = {1,3,2,5,9,4,10}, we define an array s and an array b, which stores the possible ascending sequences. s[i] represents the end element of the longest ascending subsequence of length i. Of course, the smaller the value, the better, because for an ascending sequence, the smaller the value at the end is, the easier it is to add values ​​to the back, which is one of the solutions. Greedy thinking.
For example we traverse the array a
a[1] = 1,b = {1},s[1] = {1}
a[2] = 3,b = {1,3},s[2] = {3}
a [3] = 2, since s[2]>2, so to replace the last one in b, then b = {1,2}, s[2] = {2}
a[4] = 5, b = {1,2,5},s[3] = {5}
a[5] = 9,b = {1,2,5,9},s[4] = {9}
a[6] =4, Since s[4]>4, we need to replace the first element greater than 4 in b with 4. How to find this element? Of course, the dichotomy method is used. After all, the elements in b have been sorted at this time, so there are b = {1,2,4,7}, s[4] = {7}
a[7] = 10, b = {1 ,2,4,7,10},s[5] = {10}
Finally we get the length of the longest ascending subsequence is 5, although the b at this time is not the correct longest ascending subsequence, but the length is our The result you are looking for.

#include <iostream>
#include <algorithm>

#define INF 0x3f3f3f3f

using namespace std;

int a[7] = {1,3,2,5,9,4,10};

int b[10],s[10];

int main()
{
	fill(b,b+10,INF);
	int maxs = -1;
	for(int i = 0;i<7;i++)
	{
		int j = lower_bound(b,b+10,a[i])-b;//获取第一个不小于a[i]的下标;
		s[i] = j+1;//s[i]记下的是当前的长度
		if(maxs < s[i])
		maxs = s[i];//记下最大的长度
		b[j] = a[i]; 
	}
	cout<<maxs; 
	return 0;
 } 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325249688&siteId=291194637