一、实验目的
1 掌握蛮力法的设计思想(利用计算机去穷举所有的可能解,再从中依次找出可行解)
2 掌握蛮力法的具体实现和时间复杂度分析
3 理解蛮力法的常见特性
二、实验内容
- 完成百元买百鸡\串匹配问题
- 完成求差\分数化简问题
- 问题分析
(1) 百元买百鸡:公鸡5元一只,母鸡3元一只,三只小鸡1元,所以就可以设公鸡i只,母鸡j只,小鸡k只,所以i+k+j=100,5*i+3*j+k/3=100,所以使用for循环,第一层循环,循环变量为公鸡数量,第二层循环,循环变量为母鸡的数量,第三层变量,循环变量为小鸡的数量,并且要注意小鸡的数量要能被3整除,最后输出方案即可;
(2)串匹配:首先将串A与串B的首字母对齐,然后逐个判断相对的字符是否相等,此时i和j都指向第一个字符
然后当出现匹配失败的情况,将串A往后移动一个字符的位置,再继续同串B匹配此时i指向B串的第二个字符,而j仍指向A串的第一个字符,以此类推,直到匹配成功
(3)一维数组求差:首先定义一个差值,并将其初始化为0,然后运用for循环,每次都用差值减去每个数组的值,最后得出结果返回即可
(4)分式化简:要先求出分子和分母的最大公约数,运用for循环,循环变量为分子,开始逐一递减到1,每次都判断分子和分母能不能被这个循环变量整除,若能则此时的循环变量便是最大公约数,然后分子和分母同时除以最大公约数即可。
- 问题解决
- 百元买百鸡:
(1)、算法描述:
算法:百元买百鸡 void getChicken()
过程:1、定义公鸡母鸡小鸡数量i,j,k;
2、循环变量i从1到20,j从1到33,k从1到100,重复执行以下操作;
2.1如i+j+k=100且5*i+3*j+k/3=100且k%3==0,则输出I,j,k(即百元买百鸡的方案)
(2)、算法实现
public class ch1 {
/*
百元买百鸡,公鸡5元一只,母鸡3元一只,小鸡三只一元
*/
void getChicken(){
int i,j,k;/*定义母鸡,公鸡,小鸡数*/
for (i=1; i<20; i++) /*公鸡*/
for (j=1;j<33;j++) /*母鸡*/
for (k=1;k<100;k++) /*小鸡*/
if(i+j+k==100&&i*5+j*3+k/3==100&&k%3==0)
System.out.println("母鸡有:"+i+"只,"+"公鸡有:"+j+"只,"+"小鸡有:"+k+"只。");
}
算法时间复杂度为:O(1)
(3)、运行结果
- 串匹配:
(1)、算法描述
算法:串匹配 getString(char []str,char []sub)
输入:字符串数组str,字符串数组sub
输出:串的位置
过程:1、定义循环变量i和j,并将其初始化为0;
2、当主串str和子串sub都未遍历完时,重复执行以下操作:
2.1如str[i]==sub[j],则i++;j++;
2.2如str[i]!=sub[j],则i=i-j+1;j=0;
3、如子串遍历完了之后,则返回i-j;
4、返回-1(没找到);
(2)、算法实现
int getString(char[] str, char[] sub) { /*主串str,字串sub*/
int lenStr = str.length;
int lenSub = sub.length;
int i = 0, j = 0;
while (i < lenStr && j < lenSub) {
if (str[i] == sub[j]) {
i++;
j++;
} else {
i = i - j + 1;
j = 0;
}
}
if (j >= lenSub) /*匹配完了之后如果找到则返回下标*/
return i - j;
return -1;
}
}
算法时间复杂度:假设主串长度n,子串长度m,最好O(n+m),最坏O(n*m)
(3)、运行结果
- 一维数组求差:
(1)、算法描述:
算法:一维数组求差 getDiffer(int a[],int n)
输入:一维数组a[],数组长度n
输出:一维数组之差result
过程:1、定义整型变量result,并将其初始化为0;
2、定义循环变量i并将其初始化为0;
3、循环变量i从0到n-1,重复执行以下操作
3.1、result=result-a[i];
3.2、i++;
4、返回result;
(2)、算法实现:
public class ch3 {
/*
一维数组求差
*/
int getDiffer(int []a,int n){
int result=0,i;
for (i=0;i<n;i++){
result=result-a[i]; /* 数组中的每个元素逐个相减 */
}
return result;
}
}
算法时间复杂度为O(n);
(3)、运行结果
4、分数化简:
(1)、算法描述:
算法:分式化简getSimple(int a,int b)
输入:分子a,分母b
输出:化简后的分子和分母
过程:1、定义循环变量i,并将其初始化为0;
2、循环变量i从a到1,重复以下操作
2.1、如a%i==0&&b%i==0,则a=a/i;b=b/i;
2.2、i--;
3、输出化简后的分子a和分母b
(2)、算法实现:
public class ch4 {
/*
分数化简
*/
void getSimple(int a,int b){
for(int i=a;i>=1;i--){ /* 从分子开始依次排查最大公约数 */
if ((a%i==0)&&(b%i==0)){
a=a/i;
b=b/i;
}
}
System.out.println("分式化简后为"+a+"/"+b);
}
}
算法时间复杂度为O(n)
(3)、运行结果
主函数
public class Main {
public static void main(String[] args){
/* 百元买百鸡 */
ch1 cha1=new ch1();
cha1.getChicken();
/* 串匹配 */
ch2 cha2=new ch2();
char []s={'a','b','a','c','b','a'};/* 主串 */
char []t={'c','b','a'};/* 子串 */
int k; /* 子串在主串中的位置的下标 */
k=cha2.getString(s,t);
System.out.println("子串在主串中的位置为"+k);
/* 一维数组求差 */
ch3 cha3=new ch3();
int []m={1,5,-9,100,85,-45,62,66};
int Differ;
Differ = cha3.getDiffer(m,8);
System.out.println("一维数组的差值为"+Differ);
/* 分数化简 */
ch4 cha4=new ch4();
int i=16,j=36; /* 分数16/36化简 */
cha4.getSimple(i,j);
}
}
五、实验结果总结
-
-
- 在本次蛮力法的实验中,我认识到蛮力法是一种简单直接地解决问题的方法,是一种暴力求解的方法,它的优点有适应能力很强,是唯一种几乎什么问题都能解决的一般性方法,但是它也仅限于解决小规模的问题,对于大规模的问题,它的效率会变得很低,就变得不实用了。
- 请列出对你实验中算法的改进之处。
-
对于分式化简问题,我并没有另外求分子与分母的最大公约数,而是直接用分子逐一递减来求最大公约数
-
-
- 列出你在本次实验中遇到的各种问题
-
由于对于Java语言的不熟悉,在串匹配的问题中,对于字符串数组的定义及调用屡屡碰壁,后来不断查阅资料才得以解决。