/* 1)分治算法的基本思想:将一个难以直接解决的大问题,
分割成一些规模较小的相同问题,以便各个击破,分
而治之。分治策略是:对于一个规模为n的问题,若
该问题可以容易地解决(比如说规模n较小)则直接解
决,否则将其分解为k个规模较小的子问题,这些子问
题互相独立且与原问题形式相同,递归地解这些子问题,
然后将各子问题的解合并得到原问题的解。
2)四个要素:
1.该问题的规模缩小到一定的程度就可以容易地解决
2.该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
3.利用该问题分解出的子问题的解可以合并为该问题的解;
4.该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
3)分治法在每一层递归上都有三个步骤:
1.分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
2.解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
3.合并:将各个子问题的解合并为原问题的解*/
/*汉诺塔
#include <iostream>
#include <cstdio>
using namespace std;
int count=0;
void Move(int n,char a,char c);
void hanoi(int n,char a,char b,char c);
int main()
{
hanoi(3,'A','B','C');
return 0;
}
void Move(int i,char a,char c)
{
cout<<++count<<"."<<" "<<i<<" "<<a<<"->"<<c<<endl;
}
void hanoi(int n,char a,char b,char c)
{
if(n==1) Move(1,a,c);
else
{
hanoi(n-1,a,c,b);
getchar();
Move(n,a,c);
getchar();
hanoi(n-1,b,a,c);
getchar();
}
}*/
/*棋盘覆盖
#include <iostream>
#include <cstdio>
#include <cstdlib>
int num = 0;
int Matrix[100][100];
void chessBoard(int tr, int tc, int dr, int dc, int size);
int main()
{
int size,r,c,row,col;
printf("请输入棋盘的行列号");
scanf("%d",&size);
printf("请输入特殊方格的行列号");
scanf("%d %d",&row,&col);
chessBoard(0,0,row,col,size);
for (r = 0; r < size; r++)
{
for (c = 0; c < size; c++)
{
printf("%2d ",Matrix[r][c]);
}
printf("\n");
}
return 0;
}
void chessBoard(int tr, int tc, int dr, int dc, int size)
{
int s,t;
if (size==1) return;
s = size/2; //分割棋盘
t = ++num; //L型骨牌号
if (dr < tr + s && dc < tc +s) //覆盖左上角子棋盘
{
//特殊方格在此棋盘中
chessBoard(tr,tc,dr,dc,s);
}
else //此棋盘中无特殊方格
{
//用t号L型骨牌覆盖右下角
Matrix[tr+s-1][tc+s-1] = t;
//覆盖其余方格
chessBoard(tr,tc,tr+s-1,tc+s-1,s);
}
//覆盖右上角子棋盘
if (dr < tr + s && dc >= tc + s ) //
{
//特殊方格在此棋盘中
chessBoard(tr,tc+s,dr,dc,s);
}
else //此棋盘中无特殊方格
{
//用t号L型骨牌覆盖左下角
Matrix[tr+s-1][tc+s] = t;
//覆盖其余方格
chessBoard(tr,tc+s,tr+s-1,tc+s,s);
}
//覆盖左下角子棋盘
if (dr >= tr + s && dc < tc + s)
{
//特殊方格在此棋盘中
chessBoard(tr+s,tc,dr,dc,s);
}
else
{
//用t号L型骨牌覆盖右上角
Matrix[tr+s][tc+s-1] = t;
//覆盖其余方格
chessBoard(tr+s,tc,tr+s,tc+s-1,s);
}
//覆盖右下角子棋盘
if (dr >= tr + s && dc >= tc + s)
{
//特殊方格在此棋盘中
chessBoard(tr+s,tc+s,dr,dc,s);
}
else
{
//用t号L型骨牌覆盖左上角
Matrix[tr+s][tc+s] = t;
//覆盖其余方格
chessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}*/
/*二分查找
#include <iostream>
using namespace std;
int bs(int a[],int n,int x);
int main()
{
int a[9]={0 ,1,2,3,4,5,6,7,8};
cout<<bs(a,9,1)<<endl;
}
int bs(int a[],int n,int k)
{
int l=0,r=n-1;
while(l<=r)
{
int mid=(l+r)/2;
if(a[mid]==k) return mid;
else if(a[mid]>k) r=mid-1;
else l=mid+1;
}
return -1;
}*/
/*快速排序
#include <stdio.h>
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用
void quicksort(int left, int right) {
int i, j, t, temp;
if(left > right)
return;
temp = a[left]; //temp中存的就是基准数
i = left;
j = right;
while(i != j) { //顺序很重要,要先从右边开始找
while(a[j] >= temp && i < j)
j--;
while(a[i] <= temp && i < j)//再找右边的
i++;
if(i < j)//交换两个数在数组中的位置
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
//最终将基准数归位
a[left] = a[i];
a[i] = temp;
quicksort(left, i-1);//继续处理左边的,这里是一个递归的过程
quicksort(i+1, right);//继续处理右边的 ,这里是一个递归的过程
}
int main() {
int i;
//读入数据
scanf("%d", &n);
for(i = 1; i <= n; i++)
scanf("%d", &a[i]);
quicksort(1, n); //快速排序调用
//输出排序后的结果
for(i = 1; i < n; i++)
printf("%d ", a[i]);
printf("%d\n", a[n]);
return 0;
}*/
/*归并排序
#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 500100
#define mn 1e9+10
int a[maxn];
long long int x=0;
void hb(int a[],int l,int mid,int r);
void qs(int a[],int l,int r);
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
qs(a,0,n-1);
printf("%lld\n",x);
return 0;
}
void qs(int a[],int l,int r)
{
int mid;
if(l<r)
{
mid=(l+r)/2;
qs(a,l,mid);
qs(a,mid+1,r);
hb(a,l,mid,r);
}
}
void hb(int a[],int l,int mid,int r)
{
int len1=mid-l+1;
int len2=r-mid;
int b[len1],c[len2],i,j,k ;
for(i=l,j=0,k=0;i<=r;i++)
{
if(i<=mid) b[j++]=a[i];
else c[k++]=a[i];
}
i=l,j=0,k=0;
while(j<len1&&k<len2)
{
if(b[j]<=c[k]) a[i]=b[j++];
else a[i]=c[k++];
i++;
}
while(j<len1)
{
a[i]=b[j++];
i++;
}
while(k<len2)
{
a[i]=c[k++];
i++;
}
}*/
/*有序数组才能进行二分
#include <iostream>
using namespace std;
int main()
{
int p;
cin>>p;
int a[100];
cin>>a;
int b=atrlen(a);
sort(a,a+b);
f(a,b,p);
return 0;
}
int f(int a[],int size,int p)
{
int l=0;
int r=size-1;
int last=-1;
while(l<r)
{
int mid=l+(r-l)/2;
if(a[mid]>=p)
r=mid-1;
else
{
last=mid;
l=mid;
}
}
return last;
}*/
求逆序数
#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 500100
#define mn 1e9+10
int a[maxn];
long long int x=0;
void hb(int a[],int l,int mid,int r);
void qs(int a[],int l,int r);
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
qs(a,0,n-1);
printf("%lld\n",x);
return 0;
}
void qs(int a[],int l,int r)
{
int mid;
if(l<r)
{
mid=(l+r)/2;
qs(a,l,mid);
qs(a,mid+1,r);
hb(a,l,mid,r);
}
}
void hb(int a[],int l,int mid,int r)
{
int len1=mid-l+1;
int len2=r-mid;
int b[len1],c[len2],i,j,k ;
for(i=l,j=0,k=0;i<=r;i++)
{
if(i<=mid) b[j++]=a[i];
else c[k++]=a[i];
}
i=l,j=0,k=0;
while(j<len1&&k<len2)
{
if(b[j]<=c[k]) a[i]=b[j++];
else
{
a[i]=c[k++];
x=x+len1-j;
}
i++;
}
while(j<len1)
{
a[i]=b[j++];
i++;
}
while(k<len2)
{
a[i]=c[k++];
i++;
}
}
分治
最新推荐文章于 2021-03-29 16:21:05 发布