分而治之:
中文的意思是:分别治理,利用手段使国家、民族或宗教等产生分裂,然后对其进行控制和统治。分而治之是我国古代治理国家的一种理念。 但是如何引用到计算机科学中呢?在计算机科学中,分治法是基于多项分治递归的一种很重要的算法范式。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或多个相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
关于分而治之的实现,都会经历三个步骤:
分解:将原问题分解为若干个规模较小,相对独立,与原问题形式相同的子问题。
解决:若子问题规模较小且易于解决时,则直接解。否则,递归地解决各子问题。
合并:将各子问题的解合并为原问题的解。
实际上,关于分而治之的思想,我们在前面已经使用,例如归并排序的实现,同样经历了实现分而治之的三个步骤:
分解:把数组从中间一分为二。
解决:递归地对两个子数组进行归并排序。
合并:将两个字数组合并称有序数组。
为了能够加深大家的理解,接下来通过一段代码来了解递归排序的具体实现方法。
#include<stdio.h>
#include<stdlib.h>
int fact(int n)
{
if (n ==1){
return 1;
}
return n*fact(n - 1);
}
int main()
{
int n = 0;
printf("enter a number:");
scanf("%d", &n);
printf("%d", fact(n));
system("pause");
return 0;
}
同样关于快速排序的实现,亦如此:
分:选基准,按基准把数组分成两个字数组。
解:递归地对两个字数组进行快速排序。
合:对两个字数组进行合并。
为了能够加深大家的理解,接下来通过一段代码来了解快速排序的具体实现方法。
#include <stdio.h>
#include <stdlib.h>
#define N 6
int partition(int arr[], int low, int high){
int key;
key = arr[low];
while(low<high){
while(low <high && arr[high]>= key )
high--;
if(low<high)
arr[low++] = arr[high];
while( low<high && arr[low]<=key )
low++;
if(low<high)
arr[high--] = arr[low];
}
arr[low] = key;
return low;
}
void quick_sort(int arr[], int start, int end){
int pos;
if (start<end){
pos = partition(arr, start, end);
quick_sort(arr,start,pos-1);
quick_sort(arr,pos+1,end);
}
return;
}
int main(void){
int i;
int arr[N]={32,12,7, 78, 23,45};
printf("排序前 \n");
for(i=0;i<N;i++)
printf("%d\t",arr[i]);
quick_sort(arr,0,N-1);
printf("\n 排序后 \n");
for(i=0; i<N; i++)
printf("%d\t", arr[i]);
printf ("\n");
system("pause");
return 0;
}
分而治之的例题如下:
输入格式:
输入在第一行给出两个正整数 N 和 M(均不超过10 000),分别为敌方城市个数(于是默认城市从 1 到 N编号)和连接两城市的通路条数。随后 M
行,每行给出一条通路所连接的两个城市的编号,其间以一个空格分隔。在城市信息之后给出参谋部的系列方案,即一个正整数 K (≤ 100)和随后的K 行方案,每行按以下格式给出:Np v[1] v[2] … v[Np]其中 Np 是该方案中计划攻下的城市数量,后面的系列 v[i] 是计划攻下的城市编号。
输出格式:
对每一套方案,如果可行就输出YES,否则输出NO。
输入样例:
10 11 8 7 6 8 4 5 8 4 8 1 1 2 1 4 9 8 9 1 1 10 2 4 5 4 10 3 8 4 6 6 1
7 5 4 9 3 1 8 4 2 2 8 7 9 8 7 6 5 4 2
输出样例:
NO YES YES NO NO
#include <iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN = 1e4+5;
vector<int>G[MAXN];
int aa[MAXN];
int a[MAXN];
void check(int a[]);
int n,m;
int main(){
cin >> n>>m;
while(m--){
int a,b;
cin >> a>> b;
G[a].push_back(b);
G[b].push_back(a);
}
//计算每个城市相邻点数
for(int i = 1; i <= n; i++){
aa[i] = G[i].size();
}
int k;
cin >> k;
for(int i = 0; i < k; i++){
for(int i = 1; i <= n; i++)
a[i] = aa[i];
int np;
cin >> np;
int arr[MAXN];
for(int j = 0; j < np; j++){
cin >> arr[j];
}
for(int j = 0; j < np; j++){
int t = arr[j];
a[t]=0;
for(int z = 0; z < G[t].size(); z++){
a[G[t][z]]--;
}
}
check(a);
}
return 0;
}
void check(int a[]){
bool flag = true;
for(int i = 1; i <= n; i++){
if(a[i] > 0){
flag = false;
cout << "NO" << endl;
break;
}
}
if(flag){
cout << "YES" << endl;
}
}