一、算法原理和分类

1、枚举算法分为 暴力枚举(双for)、二进制枚举、递归枚举。

2、枚举就是将题目中所有的情况都列出来,然后找到符合条件的那个答案。

二、题目详解

1、暴力枚举试题(https://www.luogu.com.cn/problem/P1003)

(1)首先我们可以创建a, b, g, k四个数组将x轴坐标、y轴坐标、x轴方向长度、y轴方向长度存储起来。

(2)通过从后向前遍历的方式找到覆盖在(x, y)这个坐标点的最上面的地毯。

(3) 对于如何确定给出的点在不在地毯上,我们可以根据  a<= x<=(a+g)  、b<=y<=(b+k)这两个不等式求得。

(4)具体代码如下:

#include <iostream>
using namespace std;
const int N = 1e6;

int n;
int a[N], b[N], g[N], k[N];
int x, y;
 
int find()
{
	for(int i = n; i >= 1; i--)
	{
		if(x >= a[i] && y >= b[i] && x <= a[i] + g[i] && y <= b[i] + k[i])
		{
			return i;
		}
	} 
	return -1;
}
int main()
{
	cin >> n;
	
	for(int i = 1; i <= n; i++)
	{
		cin >> a[i] >> b[i] >> g[i] >> k[i];
	}
	
	cin >> x >> y;
	
	cout << find();
	 
	return 0;
}

2、二进制枚举(https://leetcode.cn/problems/subsets/description/)

(1)题目要求是求一个集合的所有子集,这个我们就可以使用二进制枚举。

(2)如果一个集合里面元素的个数为n,那子集的个数则为2^n个,这和 0 ~1<< n - 1的数的二进制设置位是相同的。

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> ret;
        int num = nums.size();

        for(int i = 0; i < (1 << num); i++)
        {
            vector<int> temp;

            for(int j = 0; j < num; j++)
            {
                if((i >> j) & 1) 
                {
                    temp.push_back(nums[j]);
                }
            }

            ret.push_back(temp);
        }

        return ret;
    }
};

更多推荐