【ACM训练一】时间复杂度,递归和枚举

时间复杂度

浅显易懂的解释:https://blog.csdn.net/qq_41523096/article/details/82142747#commentsedit

常见时间复杂度(大O表示法)
(1)O(1):常量阶,运行时间为常量
(2)O(logn):对数阶,如二分搜索算法
(3)O(n):线性阶,如n个数内找最大值
(4)O(nlogn):对数阶,如快速排序算法
(5)O(n^2):平方阶,如选择排序,冒泡排序
(6)O(n^3):立方阶,如两个n阶矩阵的乘法运算
(7)O(2^n):指数阶,如n个元素集合的所有子集的算法
(8)O(n!):阶乘阶,如n个元素全部排列的算法

枚举与递归

对于定义就不解释
例题
1、枚举提高
输入一个数N (0<N<8)和一个数K (0<k<=5),要求:从1~N这N个数字中,任意选出K个数字(数字可以重复选),请按大小输出所有的方案。

#include <stdio.h>
int n,k;
int tt[9];
void di(int pt)
{
	int i;
	if(pt>k)
	{
		for(i=1;i<=k;i++)
		printf("%d",tt[i]);
		printf("\n");
	}
	else
	{
		for(i=1;i<=n;i++)
		{
		tt[pt]=i;
		di(pt+1);
	    }
	}
}
int main()
{
	scanf("%d%d",&n,&k);
	di(1);
	return 0;
}

2、全排列
输入一个数N (0<N<8),输出由1~N这N个数字组成的全排列,按从小到大的顺序。

#include<stdio.h>
#include<math.h>
int main(){
	int used[10];
	int N,i,j,k,s,t;
	int min=0,max=0;
	scanf("%d",&N);
	for(i=1;i<=N;i++)
    {
	min=min+i*pow(10,N-i);
	max=max+(N-i+1)*pow(10,N-i);
	}
	for(i=min;i<=max;i++)
	{
			used[1]=0;
			used[2]=0;
			used[3]=0;
			used[4]=0;
			used[5]=0;
			used[6]=0;
			used[7]=0;
			used[8]=0;
		for(j=1,k=i;j<=N;j++)
		{
		s=k/pow(10,N-j);
		k=k-(s*pow(10,N-j));
			switch(s)
				{
					case 0:used[0]=used[0]+1;break;
					case 1:used[1]=used[1]+1;break;
					case 2:used[2]=used[2]+1;break;
					case 3:used[3]=used[3]+1;break;
					case 4:used[4]=used[4]+1;break;
					case 5:used[5]=used[5]+1;break;
					case 6:used[6]=used[6]+1;break;
					case 7:used[7]=used[7]+1;break;
					case 8:used[8]=used[8]+1;break;
					case 9:used[9]=used[9]+1;break;
				}
		}
    for(j=1,k=0;j<=N;j++)
        {
            if(used[j]!=1)
            break;
            else 
            k=k+1;
        }
			if(k==N)
            printf("%d\n",i);
	}
}

3、N皇后
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

#include <stdio.h>
#define NUMS 10
int N;
int chessboard[11][11];
int cal;
int dfs_check(int row,int column,int k)
{
    if(row>k)
    {
        cal++;
        return 1;
    }
    int i=0;
    int j=0;
    for( i = 1; i < row; i++)
       
    if(chessboard[i][column] == 1)
    return 0;

    /* 左右上方45度角检查是否可以*/
    /* 左上方*/
    for( i=row-1,j=column-1;i>0&&j>0;i--,j--)
    if(chessboard[i][j] == 1)
    return 0;
    /* 右上方*/
    for( i=row-1,j=column+1;i>0&&j<=k;i--,j++)
    if(chessboard[i][j] == 1)
    return 0;
    /*标记这个位置成功了*/
    chessboard[row][column] = 1;

    /*进行下一行搜索*/
    for( i=1;i<=k;i++)
    if(dfs_check(row+1,i,k)==1)
    break;

    chessboard[row][column] = 0;
    return 0;
}
int main()
{
    int i,j,k;
    int count[11];
    /*打表*/
    for(k=1;k<=NUMS;k++)
    {
        count[k] = 0;
        cal = 0;
        /*首先将棋盘初始化全部置为0*/
        for(i=0;i<=NUMS;i++)
        for(j=0;j<=NUMS;j++)
        chessboard[i][j]=0;
        for(i=1;i<=k;i++)
        dfs_check(1,i,k);
        count[k] = cal;
    }

    while(scanf("%d",&N)!=EOF&&N!=0)
    printf("%d\n",count[N]);
    return 0;
}

未完待续

猜你喜欢

转载自blog.csdn.net/slozer/article/details/94644907
今日推荐