洛谷题单-暴力枚举&简单排列组合

排列枚举
P1706 全排列问题,P1088 火星人
思路:
1.搜索(未学习)
2.STL:next_permutation(start,end) 生成一个在[start,end)内存的数组严格按照字典序的下一个排列,且当为最大值时返回0
  I:手写(待补充)
补充:
1.对于全排列的升序输出STL可以轻松解决
2.利用其性质可以求任意第m个排列的后n个排列
课后小题:那么如何倒序输出排列数呢?
子集枚举
P1036 选数(枚举组合并判断)
思路:
1.搜索(未学习)
2.二进制法(对于二进制的初步了解见---)
思路:
1.将每个10进制数当成一个"集合",而0和1代表该元素是否存在
2.利用位运算符逐位判断元素是否存在并符合题意
3.统计各元素是否为指定数目
    I:STL直接统计__builtin_popcount()统计二进制下1的个数
    II:手写:while(n) cnt += n&1,n >> 1;
4.判定是否为质数(常用的数论知识(入门)见---)
代码:
#include <cstdio>
#include <iostream>
using namespace std;
bool check(int x)
{
    if (x == 0 || x == 1)
        return false;
    for (int i = 2; i * i <= x; i++)
    {
        if (!(x % i))
            return false;
    }
    return true;
}
int main()
{
    int a[22],n,k,ans = 0;
    cin >> n >> k;
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
    }
    int U = (1 << n); //U-1为全集
    for (int S = 0; S < U; S++)
    {
        if (__builtin_popcount(S) == k){
            int sum = 0;
            for (int i = 0; i < n;i++){
                if(S&(1 << i))
                    sum += a[i];
            }
            if(check(sum))
                ans++;
        }
    }
    printf("%d", ans);
}
P1157 组合数枚举
思路:
1.搜索(未学习)
2.二进制法
    I:利于二进制高位依次向低位移动的特点构造集合
    II:统计二进制中1的个数后<加工>后输出即可
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int a[22],n,k;
int main() {
    cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        a[i] = i;
    }
    int U = (1 << n)-1; 从后往前枚举
    for (int S = U; S >= 1; S--) {
        if (__builtin_popcount(S) == k) {
            //每次从左往右扫描,利用从高位到低位递减的特征来从小到大输出
            //轮不到5 3 2,也不可能(想一想为什么)
            //从右往左,会很麻烦(想一想在那种情况下会简单?)
            for (int i = n-1; i >= 0; i--) {
                if(S&(1 << i)) printf("%3d",n-a[i]);
            }
            puts("");
        }
    }
}
想一想:你能从大到小输出吗?
朴素暴力及优化
P2241 统计方形(数据加强版)
通用思路:
1.减少重复量(去重)
2.减少枚举量(根据题意缩小范围)
3.更换思路,从其他方面入手(寻找别的突破口,即别的解题特征)
该题思路:
未完待续~

答案:

for (int i = 1; i < n; i++) {if(S&(1 << i)) printf("%3d",n-a[i]);}

“反向利用进位”,同时从右往左进行

 

猜你喜欢

转载自www.cnblogs.com/Xweop/p/13373735.html