- 浏览: 290455 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
zh1159007904:
大侠,你这个程序的递归部分看不懂,能不能麻烦解释一下递归的思路 ...
求21位水仙花数(C语言实现) -
shenma_IT:
我是一楼的神马_CS哦 再次表示感谢!!
求21位水仙花数(C语言实现) -
shenma_IT:
好 万分感谢 !!
求21位水仙花数(C语言实现) -
Touch_2011:
shenma_CS 写道你好! 我看了你的代码 有好多让我佩服 ...
求21位水仙花数(C语言实现) -
Touch_2011:
乘法是模拟数学上两个数相乘,但在处理进位方面可能有点不同。比如 ...
求21位水仙花数(C语言实现)
1、分治法思想:
将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
2.分治法特征:
1) 该问题的规模缩小到一定的程度就可以容易地解决
2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
3) 利用该问题分解出的子问题的解可以合并为该问题的解;
4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
上述的第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。
3.分治法的基本步骤
分治法在每一层递归上都有三个步骤:
分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
合并:将各个子问题的解合并为原问题的解。
4.例题分析
(1)归并排序
分析:将要排序的序列每次折半分解。当只有一个元素时,这个元素显然是有序的,这时返回,然后把各个子问题合并,排序完成。对数列进行分治时一般采用折半分解和选取阀值(比这个值小的放左边,大的放右边)分解,传入的参数是第一个元素和最后一个元素的下标。
代码:
//分解
void resolve(int* a,int low,int high)
{
int mid;
if(low==high)
return;
mid=(low+high)/2;
resolve(a,low,mid);//分解左边
resolve(a,mid+1,high);//分解右边
merge(a,low,mid,high);//合并
}
(2)选择第K小元素
分析:这个题目跟快速排序的思路差不多,选取一个阀值(我选的是第一个元素)进行分解,比这个值小的是左半部分,大的是右半部分。然后比较K和这个值的下标,若相等,则这个值是第k小元素,若k更大,则第k小元素在右半部分,k更小在左半部分。当然这个题目跟快速排序的题目一样,不需要进行合并。
代码:
//同样用分治法选择第K小元素
int indexMin(int *a,int low,int high,int k)
{
int i=low,j=high,index=low;
int temp,dir=0;
//选择一个元素为临界值,把比这个数小的放左边,比它大的放右边
while(i<=j){
if(!dir)
if(a[j]<a[index]){
temp=a[j];
a[j]=a[index];
a[index]=temp;
index=j;
dir=1;
}else
j--;
if(dir)
if(a[i]>a[index]){
temp=a[i];
a[i]=a[index];
a[index]=temp;
index=i;
dir=0;
}else
i++;
}
//分三种情况
if(index==k)
return a[index];
else if(k<index)
return indexMin(a,low,index-1,k);
else
return indexMin(a,index+1,high,k);
}
(3)求一串数列(存放在a数组里面)的最大子段和
分析:进行折半分解。存在三种情况:1.最大字段和在左半部分2.最大字段和在右半部分3.最大字段由左半部分的部分元素和右半部分的部分元素组合而成。对这三种情况进行合并。
代码:
//求一串数列(存放在a数组里面)的最大子段和
int maxSum(int* a,int low,int high)
{
int i,temp=0;
int maxLeft,maxRight,maxLR;
int mid=(low+high)/2;
//当只有两个数时,最大字段和要么是第一个数,或是第二个数,或者是两者之和
if(high-low<=1){
if(a[low]+a[high]>a[low] && a[low]+a[high]>a[high])
return a[low]+a[high];
else
return a[high]>a[low]?a[high]:a[low];
}
//分解
maxLeft=maxSum(a,low,mid);//1.求左边的最大字段和
maxRight=maxSum(a,mid+1,high);//2.求右边的最大字段和
//3.当最大字段和是左边和右边的某一部分数合并而成时的最大字段和
maxLR=a[mid];
for(i=mid;i>=low;i--){
temp+=a[i];
maxLR=maxLR>temp?maxLR:temp;
}
temp=maxLR;
for(i=mid+1;i<=high;i++){
temp+=a[i];
maxLR=maxLR>temp?maxLR:temp;
}
//合并,返回三种情况中求出的最大字段和中的最大值
if(maxLR>maxRight && maxLR>maxLeft)
return maxLR;
else
return maxRight>maxLeft?maxRight:maxLeft;
}
(4)其他题目
棋盘覆盖:将棋盘进行分解,每分解一次就有四个子棋盘,其中有一个子棋盘中有特殊方格,用一个L型骨牌覆盖无特殊方格的三个棋盘的结合处,这样四个子棋盘都有特殊方格。再对每一个子棋盘进行分解,重复上述步骤。直到分解为2*2的棋盘则返回。
循环日程赛:把参赛选手分为两部分,当只有两个人时,只进行一场比赛。
求一列数中的最大值
快速排序
/*
* 归并法进行排序(分治法)
*/
#include<stdio.h>
//合并
void merge(int *a,int low,int mid,int high)
{
//把a中的两个子数组有序的合并到b数组中([low,mid]和[mid+1,high]两个数组)
int b[10];
int k=low;
int i=low,j=mid+1;//i指向第一个数组,j指向第二个数组
while(i<=mid && j<=high){
if(a[i]<a[j])
b[k++]=a[i++];
else
b[k++]=a[j++];
}
if(i<=mid)
while(i<=mid)
b[k++]=a[i++];
else if(j<=high)
while(j<=high)
b[k++]=a[j++];
//把排好序的数组b复制回a数组中对应的元素
for(i=low;i<=high;i++)
a[i]=b[i];
}
//分解
void resolve(int* a,int low,int high)
{
int mid;
if(low==high)
return;
mid=(low+high)/2;
resolve(a,low,mid);//分解左边
resolve(a,mid+1,high);//分解右边
merge(a,low,mid,high);//合并
}
void main()
{
int i;
int a[10]={4,5,14,-5,-8,2,0,3,3,1};
resolve(a,0,9);
for(i=0;i<10;i++)
printf("%-5d",*(a+i));
printf("\n");
}
/* * 最大子段和问题(分治法) * 数组中的最大值(分治法) * 选择第k小元素(分治法) */ #include<stdio.h> //求一串数列(存放在a数组里面)的最大子段和 int maxSum(int* a,int low,int high) { int i,temp=0; int maxLeft,maxRight,maxLR; int mid=(low+high)/2; //当只有两个数时,最大字段和要么是第一个数,或者是第二个数,或者是两者之和 if(high-low<=1){ if(a[low]+a[high]>a[low] && a[low]+a[high]>a[high]) return a[low]+a[high]; else return a[high]>a[low]?a[high]:a[low]; } //分解 maxLeft=maxSum(a,low,mid);//1.求左边的最大字段和 maxRight=maxSum(a,mid+1,high);//2.求右边的最大字段和 //3.当最大字段和是左边和右边的某一部分数合并而成时的最大字段和 maxLR=a[mid]; for(i=mid;i>=low;i--){ temp+=a[i]; maxLR=maxLR>temp?maxLR:temp; } temp=maxLR; for(i=mid+1;i<=high;i++){ temp+=a[i]; maxLR=maxLR>temp?maxLR:temp; } //合并,返回三种情况中求出的最大字段和中的最大值 if(maxLR>maxRight && maxLR>maxLeft) return maxLR; else return maxRight>maxLeft?maxRight:maxLeft; } //同样用分治法可以求出这个数组中的最大值 int max(int* a,int low,int high) { int maxLeft,maxRight; //当小于两个元素时,直接返回较大的那个元素 if(high-low<=1) return a[low]>a[high]?a[low]:a[high]; //分解 maxLeft=max(a,low,(low+high)/2); maxRight=max(a,(low+high)/2+1,high); //合并 return maxLeft>maxRight?maxLeft:maxRight; } //同样用分治法选择第K小元素 int indexMin(int *a,int low,int high,int k) { int i=low,j=high,index=low; int temp,dir=0; //选择一个元素为临界值,把比这个数小的放左边,比它大的放右边 while(i<=j){ if(!dir) if(a[j]<a[index]){ temp=a[j]; a[j]=a[index]; a[index]=temp; index=j; dir=1; }else j--; if(dir) if(a[i]>a[index]){ temp=a[i]; a[i]=a[index]; a[index]=temp; index=i; dir=0; }else i++; } //分三种情况 if(index==k) return a[index]; else if(k<index) return indexMin(a,low,index-1,k); else return indexMin(a,index+1,high,k); } void main() { int a[10]={-20,11,-4,13,-5,-2}; printf("max sub sum : %d\n",maxSum(a,0,6)); printf("max value : %d\n",max(a,0,6)); printf("第2小元素时 : %d\n",indexMin(a,0,6,1)); }
- 分治法分析.zip (7.7 KB)
- 下载次数: 7
- 归并排序.zip (828 Bytes)
- 下载次数: 8
- 最大子段和、最大值、第K小元素.zip (1.4 KB)
- 下载次数: 8
- 分治法ppt详解.zip (203.8 KB)
- 下载次数: 14
发表评论
-
二叉查找树(二叉排序树)的详细实现
2011-10-22 13:18 1353博客地址: http://blog.csdn.net/tou ... -
确定参赛者名单(C语言实现)
2011-07-10 10:39 1647/* 2011第二届国信蓝点 ... -
整数划分(C语言实现)
2011-07-10 10:35 5051/* 整数的划分问题。 如,对于正整数n=6,可以分划为 ... -
几种全排列的算法(C语言实现)
2011-07-07 00:14 6407/* * 几种排列组合的算法 */ #incl ... -
Playfire加密算法(C语言实现)
2011-07-06 10:13 3047这是C语言选拔赛最后一题,题目如下: /* ... -
浅析贪心算法
2011-07-05 17:46 14411.基本思路: a.顾名思义,贪心算法总是作出在当前看来最好 ... -
浅析动态规划算法
2011-07-05 15:30 18591、 ... -
浅析递归
2011-07-02 20:40 21551.递归的思想: 设计一个递归函数,明确这个递归函数的定义, ... -
浅析回溯算法
2011-06-29 22:48 29481、回溯法的基本思想 (1)在确定解空间的组织结构 ... -
高精度计算
2011-06-27 14:06 10781.大整数加法 2.大整数减法 3.大整数乘法 4.大整 ... -
浅析模拟算法
2011-06-27 07:58 19211.描述 有些问题难以找到公式或规律来解决,可以按 ... -
农夫过河的四种解法
2011-06-25 14:21 7001/* * 题目描述:有一个农夫,带着一只狼、一只羊、一颗白 ... -
各种排序算法的实现(C语言实现)
2011-06-17 22:31 1787/* * 各种基本排序算法实现(以由小到大为例) */ ... -
二叉查找树(C语言实现)
2011-06-15 23:47 2625/* * 构造一颗二叉查找树,实现树的插入、删除等基本操作 ... -
哈希表查找(C语言实现)
2011-06-15 13:38 11468/* * 题目:给定一个全部由字符串组成的字典,字符串全部 ... -
索引查找之英语词典(C语言实现)
2011-06-14 22:48 5575/* * 题目:英语词典。所有的单词存放在dictionary ... -
求最短路径的两种算法(C语言实现)
2011-06-11 11:23 28459求这个有向网中任意两点的最短路径 /* ... -
拓扑排序(C语言实现)
2011-06-10 23:09 3215对这个有向图进行拓扑排序 /* * 拓扑排序(采用邻 ... -
最小生成树(C语言实现)
2011-06-10 21:30 8882求这个网的最小生成树 /* * 普里姆算法和克鲁斯卡 ... -
邻接表存储的有向图的基本操作(C语言实现)
2011-06-06 11:47 14025/* * 邻接表存储的有向图的基本操作 */ #in ...
相关推荐
Voronoi 图的构造可以使用分治法,首先对点集依照 X 坐标排序,如果点集内点的个数小于等于三,那么可以直接构造,否则将点集拆分成为两个含点数目近似的点集进行构造,最后合并这两个点集。时间复杂度为 O(N log N...
“分”的思想源于分治法,它涉及将一个复杂的问题分解为若干个规模较小、相对简单的子问题,然后分别解决这些子问题,最后再将它们的解组合起来得到原问题的解。例如,在牛奶模板问题中,可能需要将一个大的任务拆分...
- **算法改进**:针对特定问题,可能需要调整现有算法,如使用分治策略、贪心法或回溯法,以提高算法性能。 2. **数据结构优化**: - **数据结构选择**:根据问题的需求选择合适的数据结构,如数组、链表、树、图...
周 源 -《浅析"最小表示法"思想在字符串循环同构问题中的应用》 ## 2004 何 林 -《信息学中守恒法的应用》 胡伟栋 -《减少冗余与算法优化》 金 恺 -《极限法——解决几何最优化问题的捷径》 李锐喆 -《细节...
文件大小限制只能分开上传 武 森 浅谈信息学竞赛中的“0”和“1” 贾志豪 组合游戏略述——浅谈SG游戏的若干拓展及变形 徐持衡 浅谈几类背包题 骆可强 论程序底层优化的一些...漆子超 分治算法在树的路径问题中的应用
10.漆子超《分治算法在树的路径问题中的应用》 11.罗穗骞《后缀数组——处理字符串的有力工具》 12.方展鹏《浅谈如何解决不平等博弈问题》 13.姜碧野《SPFA算法的优化及应用》 14.毛杰明《母函数的性质及应用》 15....
2. **汤可因《浅析竞赛中一类数学期望问题的解决方法》**: 数学期望是概率论中的一个重要概念,经常用于决策和优化问题。在信息学竞赛中,理解和计算数学期望对于解决涉及随机性的问题至关重要。论文可能介绍了...
汤可因的《浅析竞赛中一类数学期望问题的解决方法》则聚焦于概率论与数理统计的应用。在信息学竞赛中,数学期望是解决许多随机问题的关键,文章可能介绍了一种系统的方法来处理这些问题,包括如何建立模型,如何计算...
5. **[原创]浅析求素数算法 - LinuxSir_Org.mht**:素数检测是数论中的基础问题,也是构建其他复杂算法的基础,如素数筛法、Miller-Rabin测试等。此文档可能介绍了不同的求素数算法及其优缺点。 6. **大整数四则...
10.2. 分治法 10.3. 其他方法 10.4. 两个字种群计数的和与差 10.5. 两个字的种群计数比较 10.6. 数组中的1位种群计数 10.7. 应用 第11章 安全通信:自由的技术 11.1 项目启动之前 11.2剖析安全通信的复杂性 11.3 ...