2.7学习总结

时间:2025-02-08 08:02:03

并查集:

1.查询(采用了递归的方法)

2.合并、

完整代码模板(联系题目直接套模板)

1.优化前

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
 
int uset[MAXSIZE];//定义一个足够长的数组
//用下标来表示结点
/*
构造并查集
int size 有多少个节点
*/
void makeSet(int size)
{
	for (int i = 1; i < size; i++)
	{
		//各自为各自的代表
		uset[i] = i;
	}
}
 
/*
找到元素所在的集合的代表 如果位于同一集合 
*/
int find(int i)
{
	if (i == uset[i])
	{
		return i;
	}
	return find(uset[i]);
}
 
void unite(int x, int y) 
{
	//先找相对应的代表
	int x = find(x);
	int y = find(y);
	if (x == y)
	{
		return;
	}
	uset[x] = y;
 
}

2.优化后

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
/*
因为在特殊情况下 这棵树可能是一个长长的树链 设链的最后一个节点为x
每次执行find 相当于遍历整个链条
只需要把便利过的结点都改成跟的子节点 查询就会快很多
*/
 
 
int uset[MAXSIZE];//定义一个足够长的数组 每个结点
int rank[MAXSIZE];//树的高度
 
//用下标来表示结点
/*
构造并查集
int size 有多少个节点
*/
void makeSet(int size)
{
	for (int i = 1; i <= size; i++)
	{
		//各自为各自的代表
		uset[i] = i;
		//树的高度
		rank[i] = 0;
	}
}
 
/*
找到元素所在的集合的代表 如果位于同一集合
查找元素在哪个集合
*/
int find(int i)
{
	if (i == uset[i])
	{
		return i;
	}
	return uset[i] = find(uset[i]);//在第一次查找的时候 将结点直接连到跟
}
 
void unite(int x, int y)
{
	//先找相对应的代表
	int x = find(x);
	int y = find(y);
	if (x == y)
	{
		return;
	}
	//判断两棵树的高度 在决定谁为子树
	if (rank[x] < rank[y])
	{
		uset[x] = y;
	}
	else
	{
		uset[y] = x;
 
		if (rank[x] == rank[y])
		{
			rank[x]++;
		}
	}
}

背包问题:

1.01背包:物品有限,求取最大价值dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])

2.完全背包:物品无限,求最大价值dp[j]=max(dp[j],dp[j-w[i]]+v[i])

3.多重背包:每个物品只能拿指定数目