蛮力法
概述
蛮力法(brute force method,也称穷举法或枚举法),是一种简单直接地解决问题的方法,采用一定的策略依次处理待求解问题的所有元素,从而找出问题的解
蛮力法的关键
依次处理所有元素
- 确定穷举的范围
- 保证处理过的元素不再被处理
蛮力法的设计思想
- 找出枚举范围
- 分析问题所涉及的各种情况
- 找出约束条件
- 分析问题的解需要满足的条件,并用逻辑表达式表示
例题
百元买鸡
题目:已知公鸡 5 元一只,母鸡 3 元一只,小鸡 1 元三只,用 100 元钱买 100 只鸡,问公鸡、母鸡、小鸡各多少只
分析:
约束条件如下:,,依次代数测试是否符合条件
值得注意的是,为了减少判断次数,添加约束条件:
int Chicken(){
int x,y,z,count=0;
for (x = 0; x < 20; x++){
for ( y = 0; y < 33 ; y++){
z = 100 - x - y;
if (z%3 == 0 && z/3 + 5*x + 3*y == 100){
count++;
cout << "公鸡:" << x << "只,母鸡:" << y << "只,小鸡:" << z << "只" << endl;
}
}
}
if (count == 0){
cout << "没有符合条件的解" << endl;
}
}
串匹配问题
问题:给定两个字符串 S 和 T,在主串 S 中查找子串 T 的过程称为串匹配(string matching,也称模式匹配),T 称为模式
分析
-
朴素模式(BF算法)
从S头开始匹配,若匹配失败,从S的第二位重新匹配,以此类推
int BF(char s[],char t[]){ int i=0,j=0; int index=0; while(s[i]!='\0'&&t[j]!='\0'){ if(s[i]==t[j]){ i++; j++; } else{ i=++index; j=0; } } if(t[j]=='\0') return index; else return -1; }
-
KMP算法
- 找出模式串的next数组
-
若相同继续比较,若不同j回溯到next[j]位置
-
j=-1,则i和j均++(j下标移动到0,保证数组下标不小于0)
void getNext(char T[], int next[]){ int i, j, len; next[0] = -1; // 依次求next[j] for (j = 1; T[j] != '\0'; j++){ // 相等子串的最大长度为j-1 for (len = j - 1; len >= 1; len--){ for (i = 0; i < len; i++) if (T[i] != T[j - len + i]) break; if (i == len){ next[j] = len; break; } } if (len < 1) next[j] = 0; // 其他情况,无相等子串 } } // 求T在S中的序号 int KMP(char S[], char T[]){ int i = 0, j = 0, next[80]; getNext(T, next); while (S[i] != '\0' && T[j] != '\0'){ if (S[i] == T[j]){ i++; j++; } else{ j = next[j]; if (j == -1){ i++; j++; } } } if (T[j] == '\0') return (i - j + 1); // 返回本趟匹配的开始位置 else return 0; }
凸包问题
问题:凸包问题要求为平面上具有 n 个点的集合S构造最小凸多边形。
分析:连接图中的任意两点,若剩余点都在直线的一侧,则该线段是凸包边界上的一部分,运用蛮力法解决凸包问题,依次判断每个点到各个点的线段是否是边界的一部分。
为防止重复,只考虑 i<j 的点对。
int bulgePack(int x[],int y[],int n,int px[],int py[]){
int sign1,sign2;
int index=0;
for (int i = 0; i < n-1; i++){
for (int j = i+1; j < n; j++){
sign1 = 0;
sign2 = 0;
//计算两点组成的线段方程
int a = y[i]-y[j];
int b = x[j]-x[i];
int c = x[i]*y[j]-x[j]*y[i];
int k;
//判断剩余点是否在直线的同一侧
for (k = i; k < n; k++){
if(k!=i&&k!=j){
if(a*x[k]+b*y[k]+c>0){
sign1=1;
}else{
sign2=1;
}
if(sign1==1&&sign2==1){
break;
}
}
}
if (k==n){
px[index]=x[i];
py[index++]=y[i];
px[index]=x[j];
py[index++]=y[j];
}
}
}
return index;
}
练习
-
- 问题:设计算法将一个给定的真分数化简为最简分数,例如将6/8化简为3/4
- 实现
int simplification(int x,int y,int &a,int &b){ for (int i = 2; i <= x; i++){ if (x % i == 0 && y % i == 0){ x /= i; y /= i; i = 1; } } a = x; b = y; return 0; }
-
- 问题:判断大数能否被11整除
- 分析:从右开始两两一组,判断和能否被11整除,如561245,判断56+12+45能否被整除
- 实现:
bool divByEleven(char n[]){ int sum = 0; int i = 0; while(n[i] != '\0'){ if(i % 2 == 0) sum += n[i] - '0'; else sum += (n[i] - '0')*10; i++; } if(sum % 11 == 0) return true; return false; }
-
- 问题:计算求解mod
- 分析:取模之后再倍乘之后取模,结果一致
- 实现:
int mod(int a,int n,int m){ int r=a; while(n>0){ r%=m; r*=a; n--; } return r/a; }
-
- 问题:删除重复的元素,要求移动次数较少
- 分析:建立数组保存该元素是否出现过;设置索引值记录当前已经确定的数组位置
- 实现
int removeDuplicates(int* nums, int numsSize) { if (numsSize == 0) return 0; int hash[1001] = {0}; int i = 0; for (int j = 0; j < numsSize; j++) { if (hash[nums[j]] == 0) { hash[nums[j]] = 1; nums[i++] = nums[j]; } } return i; }
-
- 问题:A[n],调整为左边全为奇数,右边全为偶数
- 分析:类似快排的操作
- 实现:
void swap(int t[],int n){ int i=0,j=n-1; while(i<j){ if (t[i]%2==0) { if (t[j]%2==1) { int temp=t[i]; t[i]=t[j]; t[j]=temp; }else{ j--; } }else{ i++; } } }
本文作者:asdio
本文链接:https://www.cnblogs.com/agitm/p/17237140.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步