写在前面的话,步入研二面临就业和转博的十字路口,博主为了以防研究生毕业直接去工作,特此选修了一个算法课程,突然发现自己的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;
}