C++基础知识以及几个算法实现

写在前面的话,步入研二面临就业和转博的十字路口,博主为了以防研究生毕业直接去工作,特此选修了一个算法课程,突然发现自己的C++和C语言编程差到极致,为此这半年打算重点提高C++代码编程能力,接下来的博客将围绕leecode上面的一些经典算法来写代码。

校门外的树

总时间限制: 1000ms 内存限制: 65536kB
描述
某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。
马路上有一些区域要用来建地铁,这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。
输入
输入的第一行有两个整数L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。
输出
输出包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。

#include <iostream>
using namespace std;

int main()
{
    
    
    int L,M;
    cin >> L >> M;//L,M表示树和区间数目
    if (L < 1 || L > 10000 || M < 1 || M > 100)
    {
    
    
        cout << "L,M至少有一个不在范围内" << endl;
       
    }
    int i,j,Q[M][2];//Q表示区间起始点
    int count = 0;//记录剩下多少树
    for(i = 0; i < M; i++)
    {
    
    
        cin >> Q[i][0] >> Q[i][1];
    }
    int tree[L + 1];
    for(i = 0;i < L + 1; i++)
    {
    
    
        tree[i] = i;
    }
    for(i = 0; i < M; i++)
    {
    
    
        for(j = Q[i][0];j <= Q[i][1]; j++)
        {
    
    
            tree[j] += 1;
        }
    }
    for(i = 0; i < L + 1; i++)
    {
    
    
        if(tree[i] == i)
        {
    
    
            count += 1;
        }
    }
    cout << count << endl;
    return 0;
}

八皇后问题

总时间限制: 10000ms 内存限制: 65536kB
描述
在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。
输入
无输入。
输出
按给定顺序和格式输出所有八皇后问题的解(见Sample Output)。
八皇后问题可以理解为构造一个矩阵,每一行每一列只有一个1,并且两个皇后不能在一条斜线上,经过图论证明以及代码运行会发现这个问题有92种解,读者需要重点理解本人的check函数

#include <iostream>
using namespace std;

const int N = 8;
int a[8],count  = 0;//a[i]表示第i个皇后的行坐标
bool check(int *a,int n,int y)//n表示第n个皇后,y表示第n个皇后的行坐标
{
    
    
    int i;
    if(n == 0)
    {
    
    
        return true;
    }
    else
    {
    
    
        for(i = 0; i < n; i++)
        {
    
    
            if(a[i] == y || a[i] + i == y + n || a[i] - i == y - n)//abs(a[i] - y) = abs(n - i)
            {
    
    
                return false;
                break;
            }
        }
        return true;
    }

}
void printQueen(int *a)
{
    
    
    int i,j;
    
    for(j = 0; j < N; j++)
    {
    
    
        for(i = 0; i < N; i++)
        {
    
    
            cout << (a[i] == j ? 1:0) << " ";
        }
        cout << endl;
    }
}
void find_Queen(int *a,int n)
{
    
    
    int i;
    if(n >= N)
    {
    
    
        printf("No. %d\n",count + 1);
        printQueen(a);
        count++;
    }
    else
    {
    
    
        for(i = 0; i < N; i++)
        {
    
    
            if(check(a,n,i))
            {
    
    
                a[n] = i;
                find_Queen(a,n + 1);
            }
        }
    }
}
int main()
{
    
    
    find_Queen(a,0);
    //cout << "total" << count << endl;
    return 0;

区间合并问题

描述
给定 n 个闭区间 [ai; bi],其中i=1,2,…,n。任意两个相邻或相交的闭区间可以合并为一个闭区间。例如,[1;2] 和 [2;3] 可以合并为 [1;3],[1;3] 和 [2;4] 可以合并为 [1;4],但是[1;2] 和 [3;4] 不可以合并。

我们的任务是判断这些区间是否可以最终合并为一个闭区间,如果可以,将这个闭区间输出,否则输出no。

输入
第一行为一个整数n,3 ≤ n ≤ 50000。表示输入区间的数量。
之后n行,在第i行上(1 ≤ i ≤ n),为两个整数 ai 和 bi ,整数之间用一个空格分隔,表示区间 [ai; bi](其中 1 ≤ ai ≤ bi ≤ 10000)。
输出
输出一行,如果这些区间最终可以合并为一个闭区间,输出这个闭区间的左右边界,用单个空格隔开;否则输出 no。
这个问题本人的亮点是采取了快速排序算法,相比于冒泡排序,这个算法复杂度为O(Nlog(N)),不过这个算法本人也没有特别理解

#include <iostream>
using namespace std;

void quickSort(int left, int right, int arr[][2])
{
    
    
	if(left >= right)
		return;
	int i, j, base0,base1, t0,t1;
	i = left, j = right;
	base0 = arr[left][0];  //取最左边的数为基准数
    base1 = arr[left][1];
	while (i < j)
	{
    
    
		while (arr[j][0] >= base0 && i < j)
			j--;
		while (arr[i][0] <= base0 && i < j)
			i++;
		if(i < j)
		{
    
    
			t0 = arr[i][0];
            t1 = arr[i][1];
			arr[i][0] = arr[j][0];
            arr[i][1] = arr[j][1];
			arr[j][0] = t0;
            arr[j][1] = t1;
		}
	}
	//基准数归位
	arr[left][0] = arr[i][0];
    arr[left][1] = arr[i][1];
	arr[i][0] = base0;
    arr[i][1] = base1;
	quickSort(left, i - 1, arr);//递归左边
	quickSort(i + 1, right, arr);//递归右边
}
int main()
{
    
    
    int N;
    cin >> N;
    int i,Q[N][2];
    bool tmp;
    for(i = 0; i < N; i++)
    {
    
    
        cin >> Q[i][0] >> Q[i][1];
    }
    quickSort(0,N - 1,Q);
    int Qend[2] = {
    
    Q[0][0],Q[0][1]};
    
    for(i = 0; i < N - 1; i++)
    {
    
    
        if(Qend[1] < Q[i + 1][0])
        {
    
    
            tmp = false;
            
        }
        else if(Qend[1] >= Q[i + 1][0] && Qend[1] <= Q[i + 1][1])
        {
    
    
            Qend[1] = Q[i + 1][1];
            tmp = true;
        }
        else
        {
    
    
            tmp = true;
            continue;
        }
    }
    if(tmp)
    {
    
    
        cout << Qend[0] << " " << Qend[1] << endl;
    }
    else
    {
    
    
        cout << "no" << endl;
    }
    
}

红黑瓷砖问题

总时间限制: 1000ms 内存限制: 65536kB
描述
There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can’t move on red tiles, he can move only on black tiles.

Write a program to count the number of black tiles which he can reach by repeating the moves described above.
输入
The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20.

There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.

‘.’ - a black tile
‘#’ - a red tile
‘@’ - a man on a black tile(appears exactly once in a data set)
The end of the input is indicated by a line consisting of two zeros.
输出
For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).

#include <iostream>
#include <cstdio>
using namespace std;

const int dir[4][2] = {
    
    {
    
    -1,0},{
    
    1,0},{
    
    0,-1},{
    
    0,1}};
char mat[20][20];
int count = 1;
int M,N;

void search(int x,int y,int M,int N)
{
    
    
    
    mat[x][y] = '#';
    int i,nx,ny;
    for(i = 0; i < 4; i++)
    {
    
    
        nx = x + dir[i][0];
        ny = y + dir[i][1];
        //printf("nx:%d,ny:%d,M:%d,N:%d,mat[nx][ny]:%c\n",nx,ny,M,N,mat[nx][ny]);
        //cout << (nx >= 0) << (nx < N) << (ny >= 0) << (ny < M) << (mat[nx][ny] == '.') << endl;
        if(nx >= 0 && nx < N && ny >= 0 && ny < M && mat[nx][ny] == '.')
        {
    
    
            //cout << "-------------" << endl;
            count++;
            search(nx,ny,M,N);
        }
    }
    
}
int main()
{
    
    
    //int count = 1;
    int i,j;
    int axis[2];//储存人的位置
    while(cin >> M >> N && M <= 20 && N <= 20)  
    {
    
    
        if(M == 0 && N == 0)
        {
    
    
            break;
        }
        for(i = 0; i < N; i++)
        {
    
    
            for(j = 0; j < M; j++)
            {
    
    
                cin >> mat[i][j];
                if(mat[i][j] == '@')
                {
    
    
                    axis[0] = i;
                    axis[1] = j;
                }
            }
        }
        //cout << M << " " << N;
        search(axis[0],axis[1],M,N);
        cout << count << endl;
        count = 1;
    }
    
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/forrestguang/article/details/120351364