ACM-ICPC基本算法思想

正在更新中

  • 求值法

  • 递推法

  • 递归法

  • 枚举法

  • 模拟法

    将自然的过程或者语言直白的程序化,比如题目中的求解过程,我们直接程序化模拟求解。即根据实际问题建立模型,模拟实际玩法从而解决问题。
    (1)随机模拟

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	int i,s;
	long t;
	cin>>n;
	t=time(NULL)%1000;   //rand()%(b-a+1)+a;    rand()%(80-20+1)+20 
	srand(t);
	for(t=0,i=1;i<=n;i++)
	t=t+rand()%61+20;
	s=t/10;
	cout<<s;
	return 0;
}

(2)过程模拟

在这里插入图片描述
问题分析:输入第一行n代表有几组数,输入第二行m代表电梯要停几层,随后跟着输入m个数代表要电梯停的楼层

每上一层楼电梯要用6分钟,每下一层楼电梯要用4分钟,在楼层中停要用5分钟


#include<bits/stdc++.h>
using namespace std;
int main(){
	int N;
	while(cin>>N,N!=0){
		int t=0;
		int sum=0;
		while(N--){
			int s;
			cin>>s;
			if(s-t>0)
			sum=sum+(s-t)*6+5;
			else
			sum=sum+(t-s)*4+5;
			t=s;
		}
		cout<<sum<<endl;
	}
	return 0;
}
  • 分治法

    在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……
      任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算。n=2时,只要作一次比较即可排好序。n=3时只要作3次比较即可,…。而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。这时候,分治法就起很大的作用了。
    在这里插入图片描述
#include<bits/stdc++.h>
using namespace std;
int w[1000001];
void gold(int low,int high,int *max,int *min){
	int x1,x2,y1,y2;
	int mid;
	if(low==high)
	*max=*min=w[low];
	else if((high-low)==1){
		if(w[high]>w[low]){
			*max=w[high];
			*min=w[low];
		} 
		else{
			*max=w[low];
			*min=w[high];
		}
	} 
	else{
		mid=(low+high)/2;
		gold(low,mid,&x1,&y1);
		gold(mid+1,high,&x2,&y2);
		*max=(x1>x2)?x1:x2;
		*min=(y1<y2)?y1:y2;
	}
}
int main(){
	int m,i;
	int max,min;
	cin>>m;
	for(i=1;i<=m;i++){
		cin>>w[i];
	}
	gold(1,m,&max,&min);
	cout<<max<<" "<<min;
	return 0;
}
  • 贪心法

  • 回溯法

回溯法又称为试探法,是一种在解空间中搜索问题解的方法。

  • 构造法

构造法是通过构造数学模型或方法解决问题的。
构造法解题类型有:
(1)数学建模
(2)直接构造

  • 动态规划法

/*数塔问题  动态规划法*/
/*动态规划并不是贪心,贪心是逐步获得最优解,其分解的子问题是相互独立得 
  而动态规划是求解决策过程最优化,其分解的子问题并不相互独立*/ 
#include<bits/stdc++.h>
using namespace std;
#define N 50
int a[N][N][3];
int n;
void operate(){
	int i,j;
	for(i=n-1;i>=1;i--)				//从底向上计算 
	for(j=1;j<=i;j++){
		if(a[i+1][j][2]>a[i+1][j+1][2])
		a[i][j][2]+=a[i+1][j][2];
		else{
			a[i][j][2]+=a[i+1][j+1][2];
			a[i][j][0]=1;
		} 
	}
} 
int main(){
	int i,j;
	cin>>n;
	for(i=1;i<=n;i++)
	for(j=1;j<=i;j++){
		cin>>a[i][j][1];
		a[i][j][2]=a[i][j][1];
		a[i][j][0]=0;
	}
	operate();
	cout<<a[1][1][2]<<endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章