main.cpp
来自「我做的一些C语言练习题,里面一共有76道题目,主要用到一些计算机常用的算法,如:」· C++ 代码 · 共 232 行
CPP
232 行
/******************************************************************************
71. (最长连线) 设有一个 N×N 的方格图形,且 N 为 3 的倍数。要求在图形中
存放 0 或 1,相邻的 1 可以连成一条连线,连接的方法可以是行,也可以是列;
同时约定一条连线只能有一个起点和一个终点,图形上的点最多只能访问一次。
编程求最长连线. 例如 N=6 时,有下图:
1 2 3 4 5 6
┌─┬─┬─┬─┬─┬─┐
1 │1│1│1│0│0│1│
├─┼─┼─┼─┼─┼─┤
2 │1│1│0│1│1│1│
├─┼─┼─┼─┼─┼─┤
3 │0│0│0│1│0│1│
├─┼─┼─┼─┼─┼─┤
4 │1│1│0│1│1│1│
├─┼─┼─┼─┼─┼─┤
5 │0│1│0│0│0│0│
├─┼─┼─┼─┼─┼─┤
6 │1│1│1│1│0│0│
└─┴─┴─┴─┴─┴─┘
在该图中,包含有如下的一些连线:
1←1←1 1←1 1
↓ ↓ ↓
1→1 1 1→1 1
↓ ↑ ↓
1→1→1 1 1
↑ ↓
1←1←1
在以上的连线中,最长的连线为: 表示方法:
1 最长连线长度:LMAX=9
↓ 连线:(1,6)→(2,6)→
1→1 1 (3,6)→(4,6)→
↑ ↓ (4,5)→(4,4)→
1 1 (3,4)→(2,4)→
↑ ↓ (2,5)
1←1←1 连线的表示不是唯一的,仅给出一种即可。
*****************************************************************************/
/*
//分治法求解
#include <stdio.h>
typedef struct
{
int x;
int y;
} Pos;
#define N 6
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
int map[N][N] = {1,1,1,0,0,1,
1,1,0,1,1,1,
0,0,0,1,0,1,
1,1,0,1,1,1,
0,1,0,0,0,0,
1,1,1,1,0,0};
Pos Line[N*N];
Pos MaxLine[N*N];
//连线
void join(int x, int y, int k, int *pmax)
{
int i;
Line[k].x = x;
Line[k].y = y;
map[y][x] = 0;
for(i=0; i<4; i++)//分治
{
#define CHECKED(x,y) x>=0 && x<N && y>=0 && y<N && map[y][x] == 1
if(CHECKED(x+dx[i],y+dy[i]))
{
join(x+dx[i],y+dy[i],k+1,pmax);
}
}
map[y][x] = 1;
//找到一条路径
if(k+1 > *pmax)
{
int t;
*pmax = k+1;
for(t=0; t<=*pmax; t++)
MaxLine[t] = Line[t];
}
}
//打印路径
void PrintMaxLine(int max)
{
int i;
printf("max = %d\n",max);
for(i=0; i<max; i++)
{
printf("(%d , %d) ",MaxLine[i].x+1,MaxLine[i].y+1);
}
printf("\n");
}
void main()
{
int x,y;
int max = 0;
for(y=0; y<N; y++)
{
for(x=0; x<N; x++)
{
if(map[y][x] == 1)
join(x,y,0,&max);
}
}
PrintMaxLine(max);
}
*/
//用回溯法求解
#include <stdio.h>
typedef struct
{
int x;
int y;
} Pos;
#define N 6
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
int map[N][N] = {1,1,1,0,0,1,
1,1,0,1,1,1,
0,0,0,1,0,1,
1,1,0,1,1,1,
0,1,0,0,0,0,
1,1,1,1,0,0};
Pos Line[N*N];
Pos MaxLine[N*N];
int path[N*N];
int join(int x, int y)
{
int k;
int max = 0;
if(map[y][x] == 0)
return 0;
Line[0].x = x;
Line[0].y = y;
for(k=0; k<N*N; k++)
path[k] = -1;
map[y][x] = 0;
k = 0;
while(k>=0)
{
while(++path[k]<4)
{
int tx,ty;
tx = x + dx[path[k]];
ty = y + dy[path[k]];
if(tx>=0 && tx<N && ty>=0 && ty<N && map[ty][tx] == 1)
{
map[y][x] = 0;
x = tx;
y = ty;
k++;
}
}
//找到从该点出发的一条路径
if(max < k)//如果大于当前最大长度,保存
{
int i;
max = k;
for(i=0; i<max; i++)
{
//保存从该点出发的最长路径
Line[i+1].x = Line[i].x + dx[path[i]];
Line[i+1].y = Line[i].y + dy[path[i]];
}
}
//回溯
map[y][x] = 1;
path[k] = -1;
k--;
if(k<0)
{
break;
}
x = x - dx[path[k]];
y = y - dy[path[k]];
}
map[y][x] = 1;
return max;
}
void PrintMaxLine(int max)
{
int i;
printf("max = %d\n",max+1);
for(i=0; i<=max; i++)
{
printf("(%d,%d) ",MaxLine[i].x+1,MaxLine[i].y+1);
}
printf("\n");
}
void main()
{
int len;
int x, y;
int max = 0;
for(y=0; y<N; y++)
{
for(x=0; x<N; x++)
{
len = join(x,y);
if(max < len)
{
int i;
max = len;
for(i=0; i<=max; i++)
MaxLine[i] = Line[i];
}
}
}
PrintMaxLine(max);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?