《程序员》算法擂台之骑士聚会问题(c语言版) 二
很明显,思考1比思考2要难多了,所以先做思考2.呵呵^_^
思考2
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
struct point
{
int x;
int y;
int* CastStep;
};
point* GetCanGo(point,int);
void Walk(point,int);
bool IsABomp(point);
int index = 0;//当前的起点下标
int rows = 0;
int cells = 0;
point** Chessboard;
point* StartPoint;
point* Bomp;//保存炸弹座标
int ZaDan = 0;//炸弹个数
void main()
{
int StartNum = 0;
printf("欢迎使用神奇的棋盘(地雷版)^_^\n");
printf("输入棋盘的行数:");
scanf(" %d",&rows);
printf("输入棋盘的列数:");
scanf(" %d",&cells);
printf("您使用了%d X %d的棋盘,输入的座标x必须在0-%d之间 y必须在0-%d之间\n",rows,cells,rows-1,cells-1);
Chessboard = (point**)malloc(4*rows);
for(int e=0;e<rows;e++)
{
Chessboard[e] = (point*)malloc(sizeof(point)*cells);
}
printf("请输入起点个数:");
scanf("%d",&StartNum);
for(int i=0;i<rows;i++)//初始化棋盘
{
for(int j=0;j<cells;j++)
{
Chessboard[i][j].x = i;
Chessboard[i][j].y = j;
Chessboard[i][j].CastStep = (int*)malloc(4 * StartNum);
for(int a=0;a<StartNum;a++)
Chessboard[i][j].CastStep[a] = 0;
}
}
StartPoint = (point*)malloc(sizeof(point)*StartNum);
for(int k=0;k<StartNum;k++)
{
printf("输入第%d个起点的座标\nx=",k+1);
scanf("%d",&StartPoint[k].x);
printf("y=");
scanf("%d",&StartPoint[k].y);
}
printf("输入地雷个数:");
scanf("%d",&ZaDan);
Bomp = (point*)malloc(sizeof(point) * ZaDan);
for(int h=0;h<ZaDan;h++)
{
printf("请输入第%d个地雷的座标\nx=",h+1);
scanf(" %d",&Bomp[h].x);
printf("y=");
scanf(" %d",&Bomp[h].y);
}
printf("必须信息读取完毕!\n计算中");
long start = clock();
for(index=0;index<StartNum;index++)//让每个起点走遍整个棋盘
{
Walk(StartPoint[index],0);
}
int CastSteps = 0;
int CastDays = 0;
point LastPoint;
for(int a=0;a<rows;a++)
{
for(int b=0;b<cells;b++)
{
int sum=0;
int max=0;
for(int c=0;c<StartNum;c++)
{
sum += Chessboard[a][b].CastStep[c];
if(Chessboard[a][b].CastStep[c] > max)
max = Chessboard[a][b].CastStep[c];
}
if(CastSteps >= sum && CastDays >= max)
{
CastSteps = sum;
CastDays = max;
LastPoint = Chessboard[a][b];
continue;
}
if(CastSteps == 0)
{
CastSteps = sum;
CastDays = max;
LastPoint = Chessboard[a][b];
}
}
}
long end = clock();
printf("\n计算完毕,用时:%ld毫秒\n会聚地点:(%d,%d)\n需要的时间:%d天\n所有人总共花去时间:%d天\n",end-start,LastPoint.x,LastPoint.y,CastDays,CastSteps);
printf("输入任意字符退出");
char temp;
scanf(" %c",&temp);
}
int count = 0;//保存下一次能走的点的个数
void Walk(point nowPoint,int SumSteps)
{
Chessboard[nowPoint.x][nowPoint.y].CastStep[index] = SumSteps;
point* NextCanGo = GetCanGo(nowPoint,++SumSteps);//在这里累加的注意咯
int num = count;
for(int i=0;i<num;i++)
{
if(IsABomp(NextCanGo[i]))//如果是炸弹则避开
continue;
Walk(NextCanGo[i],SumSteps);
}
}
bool IsABomp(point p)//判断是否为一个炸弹
{
for(int i=0;i<ZaDan;i++)
{
if(Bomp[i].x == p.x && Bomp[i].y == p.y)
return true;
}
return false;
}
point* GetCanGo(point nowPoint,int SumSteps)//得到下一步可以走的点
{
count = 0;
point temp[8];
if((nowPoint.x-1 >= 0 && nowPoint.y+2 < cells) && (Chessboard[nowPoint.x-1][nowPoint.y+2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-1][nowPoint.y+2].CastStep[index]))
{
count++;
temp[0].x = nowPoint.x-1;
temp[0].y = nowPoint.y+2;
}
else
temp[0].x = -1;//为了标记用
if((nowPoint.x-1 >= 0 && nowPoint.y-2 > 0) && (Chessboard[nowPoint.x-1][nowPoint.y-2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-1][nowPoint.y-2].CastStep[index]))
{
count++;
temp[1].x = nowPoint.x-1;
temp[1].y = nowPoint.y-2;
}
else
temp[1].x = -1;//为了标记用
if((nowPoint.x+1 < rows && nowPoint.y+2 < cells) && (Chessboard[nowPoint.x+1][nowPoint.y+2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+1][nowPoint.y+2].CastStep[index]))
{
count++;
temp[2].x = nowPoint.x+1;
temp[2].y = nowPoint.y+2;
}
else
temp[2].x = -1;//为了标记用
if((nowPoint.x+1 < rows && nowPoint.y-2 >= 0) && (Chessboard[nowPoint.x+1][nowPoint.y-2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+1][nowPoint.y-2].CastStep[index]))
{
count++;
temp[3].x = nowPoint.x+1;
temp[3].y = nowPoint.y-2;
}
else
temp[3].x = -1;//为了标记用
if((nowPoint.x+2 < rows && nowPoint.y+1 < cells) && (Chessboard[nowPoint.x+2][nowPoint.y+1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+2][nowPoint.y+1].CastStep[index]))
{
count++;
temp[4].x = nowPoint.x+2;
temp[4].y = nowPoint.y+1;
}
else
temp[4].x = -1;//为了标记用
if((nowPoint.x+2 < rows && nowPoint.y-1 >= 0) && (Chessboard[nowPoint.x+2][nowPoint.y-1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+2][nowPoint.y-1].CastStep[index]))
{
count++;
temp[5].x = nowPoint.x+2;
temp[5].y = nowPoint.y-1;
}
else
temp[5].x = -1;//为了标记用
if((nowPoint.x-2 >= 0 && nowPoint.y+1 < cells) && (Chessboard[nowPoint.x-2][nowPoint.y+1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-2][nowPoint.y+1].CastStep[index]))
{
count++;
temp[6].x = nowPoint.x-2;
temp[6].y = nowPoint.y+1;
}
else
temp[6].x = -1;//为了标记用
if((nowPoint.x-2 >= 0 && nowPoint.y-1 >= 0) && (Chessboard[nowPoint.x-2][nowPoint.y-1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-2][nowPoint.y-1].CastStep[index]))
{
count++;
temp[7].x = nowPoint.x-2;
temp[7].y = nowPoint.y-1;
}
else
temp[7].x = -1;//为了标记用
point* re = (point*)malloc(sizeof(point) * count);
int t = 0;
for(int i=0;i<8;i++)
{
if(temp[i].x != -1)
{
re[t] = temp[i];
t++;
}
}
return re;
}
#include <stdlib.h>
#include<time.h>
struct point
{
int x;
int y;
int* CastStep;
};
point* GetCanGo(point,int);
void Walk(point,int);
bool IsABomp(point);
int index = 0;//当前的起点下标
int rows = 0;
int cells = 0;
point** Chessboard;
point* StartPoint;
point* Bomp;//保存炸弹座标
int ZaDan = 0;//炸弹个数
void main()
{
int StartNum = 0;
printf("欢迎使用神奇的棋盘(地雷版)^_^\n");
printf("输入棋盘的行数:");
scanf(" %d",&rows);
printf("输入棋盘的列数:");
scanf(" %d",&cells);
printf("您使用了%d X %d的棋盘,输入的座标x必须在0-%d之间 y必须在0-%d之间\n",rows,cells,rows-1,cells-1);
Chessboard = (point**)malloc(4*rows);
for(int e=0;e<rows;e++)
{
Chessboard[e] = (point*)malloc(sizeof(point)*cells);
}
printf("请输入起点个数:");
scanf("%d",&StartNum);
for(int i=0;i<rows;i++)//初始化棋盘
{
for(int j=0;j<cells;j++)
{
Chessboard[i][j].x = i;
Chessboard[i][j].y = j;
Chessboard[i][j].CastStep = (int*)malloc(4 * StartNum);
for(int a=0;a<StartNum;a++)
Chessboard[i][j].CastStep[a] = 0;
}
}
StartPoint = (point*)malloc(sizeof(point)*StartNum);
for(int k=0;k<StartNum;k++)
{
printf("输入第%d个起点的座标\nx=",k+1);
scanf("%d",&StartPoint[k].x);
printf("y=");
scanf("%d",&StartPoint[k].y);
}
printf("输入地雷个数:");
scanf("%d",&ZaDan);
Bomp = (point*)malloc(sizeof(point) * ZaDan);
for(int h=0;h<ZaDan;h++)
{
printf("请输入第%d个地雷的座标\nx=",h+1);
scanf(" %d",&Bomp[h].x);
printf("y=");
scanf(" %d",&Bomp[h].y);
}
printf("必须信息读取完毕!\n计算中");
long start = clock();
for(index=0;index<StartNum;index++)//让每个起点走遍整个棋盘
{
Walk(StartPoint[index],0);
}
int CastSteps = 0;
int CastDays = 0;
point LastPoint;
for(int a=0;a<rows;a++)
{
for(int b=0;b<cells;b++)
{
int sum=0;
int max=0;
for(int c=0;c<StartNum;c++)
{
sum += Chessboard[a][b].CastStep[c];
if(Chessboard[a][b].CastStep[c] > max)
max = Chessboard[a][b].CastStep[c];
}
if(CastSteps >= sum && CastDays >= max)
{
CastSteps = sum;
CastDays = max;
LastPoint = Chessboard[a][b];
continue;
}
if(CastSteps == 0)
{
CastSteps = sum;
CastDays = max;
LastPoint = Chessboard[a][b];
}
}
}
long end = clock();
printf("\n计算完毕,用时:%ld毫秒\n会聚地点:(%d,%d)\n需要的时间:%d天\n所有人总共花去时间:%d天\n",end-start,LastPoint.x,LastPoint.y,CastDays,CastSteps);
printf("输入任意字符退出");
char temp;
scanf(" %c",&temp);
}
int count = 0;//保存下一次能走的点的个数
void Walk(point nowPoint,int SumSteps)
{
Chessboard[nowPoint.x][nowPoint.y].CastStep[index] = SumSteps;
point* NextCanGo = GetCanGo(nowPoint,++SumSteps);//在这里累加的注意咯
int num = count;
for(int i=0;i<num;i++)
{
if(IsABomp(NextCanGo[i]))//如果是炸弹则避开
continue;
Walk(NextCanGo[i],SumSteps);
}
}
bool IsABomp(point p)//判断是否为一个炸弹
{
for(int i=0;i<ZaDan;i++)
{
if(Bomp[i].x == p.x && Bomp[i].y == p.y)
return true;
}
return false;
}
point* GetCanGo(point nowPoint,int SumSteps)//得到下一步可以走的点
{
count = 0;
point temp[8];
if((nowPoint.x-1 >= 0 && nowPoint.y+2 < cells) && (Chessboard[nowPoint.x-1][nowPoint.y+2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-1][nowPoint.y+2].CastStep[index]))
{
count++;
temp[0].x = nowPoint.x-1;
temp[0].y = nowPoint.y+2;
}
else
temp[0].x = -1;//为了标记用
if((nowPoint.x-1 >= 0 && nowPoint.y-2 > 0) && (Chessboard[nowPoint.x-1][nowPoint.y-2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-1][nowPoint.y-2].CastStep[index]))
{
count++;
temp[1].x = nowPoint.x-1;
temp[1].y = nowPoint.y-2;
}
else
temp[1].x = -1;//为了标记用
if((nowPoint.x+1 < rows && nowPoint.y+2 < cells) && (Chessboard[nowPoint.x+1][nowPoint.y+2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+1][nowPoint.y+2].CastStep[index]))
{
count++;
temp[2].x = nowPoint.x+1;
temp[2].y = nowPoint.y+2;
}
else
temp[2].x = -1;//为了标记用
if((nowPoint.x+1 < rows && nowPoint.y-2 >= 0) && (Chessboard[nowPoint.x+1][nowPoint.y-2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+1][nowPoint.y-2].CastStep[index]))
{
count++;
temp[3].x = nowPoint.x+1;
temp[3].y = nowPoint.y-2;
}
else
temp[3].x = -1;//为了标记用
if((nowPoint.x+2 < rows && nowPoint.y+1 < cells) && (Chessboard[nowPoint.x+2][nowPoint.y+1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+2][nowPoint.y+1].CastStep[index]))
{
count++;
temp[4].x = nowPoint.x+2;
temp[4].y = nowPoint.y+1;
}
else
temp[4].x = -1;//为了标记用
if((nowPoint.x+2 < rows && nowPoint.y-1 >= 0) && (Chessboard[nowPoint.x+2][nowPoint.y-1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+2][nowPoint.y-1].CastStep[index]))
{
count++;
temp[5].x = nowPoint.x+2;
temp[5].y = nowPoint.y-1;
}
else
temp[5].x = -1;//为了标记用
if((nowPoint.x-2 >= 0 && nowPoint.y+1 < cells) && (Chessboard[nowPoint.x-2][nowPoint.y+1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-2][nowPoint.y+1].CastStep[index]))
{
count++;
temp[6].x = nowPoint.x-2;
temp[6].y = nowPoint.y+1;
}
else
temp[6].x = -1;//为了标记用
if((nowPoint.x-2 >= 0 && nowPoint.y-1 >= 0) && (Chessboard[nowPoint.x-2][nowPoint.y-1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-2][nowPoint.y-1].CastStep[index]))
{
count++;
temp[7].x = nowPoint.x-2;
temp[7].y = nowPoint.y-1;
}
else
temp[7].x = -1;//为了标记用
point* re = (point*)malloc(sizeof(point) * count);
int t = 0;
for(int i=0;i<8;i++)
{
if(temp[i].x != -1)
{
re[t] = temp[i];
t++;
}
}
return re;
}
思考1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
//先还是让每个起点走遍整个棋盘,不过这里不光去记录步数了,还要记录路径才行,因为国王可能会和骑士想遇,
//再国王去“访问”最佳聚会位置,计算所需要的步数,再访问第二佳的位置,到某个位置时会出现到它的步数和(不包国王的跳步)
//都要大于后面的包括国王在内的位置的和,这就可以返回了^_^
//记录路径最新办法:在每一个点上添加一个指针指向它的上一个点,哈哈最后的会聚点必然可以逆着找到跳到它这里的一条完整的路径
struct point
{
int x;
int y;
int* CastStep;
point** ascending;//保存上一个点
};
point* GetCanGo(point,int);
void Walk(point,int);
int KinVisit(point);
int index = 0;//当前的起点下标
int rows = 0;
int cells = 0;
point** Chessboard;
point* StartPoint;
point Kin;
int StartNum = 0;
void main()
{
printf("欢迎使用神奇的棋盘(国王版)^_^\n");
printf("输入棋盘的行数:");
scanf(" %d",&rows);
printf("输入棋盘的列数:");
scanf(" %d",&cells);
printf("您使用了%d X %d的棋盘,输入的座标x必须在0-%d之间 y必须在0-%d之间\n",rows,cells,rows-1,cells-1);
Chessboard = (point**)malloc(4*rows);
for(int e=0;e<rows;e++)
{
Chessboard[e] = (point*)malloc(sizeof(point)*cells);
}
printf("请输入起点个数:");
scanf("%d",&StartNum);
for(int i=0;i<rows;i++)//初始化棋盘
{
for(int j=0;j<cells;j++)
{
Chessboard[i][j].x = i;
Chessboard[i][j].y = j;
Chessboard[i][j].CastStep = (int*)malloc(4 * StartNum);
Chessboard[i][j].ascending = (point**)malloc(4 * StartNum);
for(int a=0;a<StartNum;a++)
Chessboard[i][j].CastStep[a] = 0;
}
}
StartPoint = (point*)malloc(sizeof(point)*StartNum);
for(int k=0;k<StartNum;k++)
{
printf("输入第%d个起点的座标\nx=",k+1);
scanf("%d",&StartPoint[k].x);
printf("y=");
scanf("%d",&StartPoint[k].y);
}
printf("输入国王座标:\nx=");
scanf("%d",&Kin.x);
printf("y=");
scanf("%d",&Kin.y);
printf("必须信息读取完毕!\n计算中");
long start = clock();//开始计时
for(index=0;index<StartNum;index++)//让每个起点走遍整个棋盘
{
Walk(StartPoint[index],0);
}
int CastSteps = 0;
int CastDays = 0;
point LastPoint;
for(int a=0;a<rows;a++)//这里开始搜索最佳聚会地点了
{
for(int b=0;b<cells;b++)
{
int sum=0;
int max=0;
for(int c=0;c<StartNum;c++)
{
sum += Chessboard[a][b].CastStep[c];//统计总步数
if(Chessboard[a][b].CastStep[c] > max)//寻找最大的步数
max = Chessboard[a][b].CastStep[c];
}
int te = KinVisit(Chessboard[a][b]);//得到国王到达需要的最少步数
if(te > max)
max = te;
sum += te;
if(CastSteps >= sum && CastDays >= max)
{
CastSteps = sum;
CastDays = max;
LastPoint = Chessboard[a][b];
continue;
}
if(CastSteps == 0)
{
CastSteps = sum;
CastDays = max;
LastPoint = Chessboard[a][b];
}
}
}
long end = clock();//结束计时
printf("\n计算完毕,用时:%ld毫秒\n会聚地点:(%d,%d)\n需要的时间:%d天\n所有人总共花去时间:%d天\n",end-start,LastPoint.x,LastPoint.y,CastDays,CastSteps);
printf("输入任意字符退出..");
char c;
scanf(" %c",&c);
}
int count = 0;//保存下一次能走的点的个数
void Walk(point nowPoint,int SumSteps)
{
Chessboard[nowPoint.x][nowPoint.y].CastStep[index] = SumSteps;
point* NextCanGo = GetCanGo(nowPoint,++SumSteps);//在这里累加的注意咯
int num = count;
for(int i=0;i<num;i++)
{
Chessboard[NextCanGo[i].x][NextCanGo[i].y].ascending[index] = &nowPoint;//在这里记录上一个位置
Walk(NextCanGo[i],SumSteps);
}
}
int KinVisit(point endPoint)//国王出发访问咯,返回最佳步数
{
int GoodSteps = abs(endPoint.x - Kin.x) + abs(endPoint.y - Kin.y);//无疑这是最大的情况
int temp = 0;
point p;
for(int i=0;i<StartNum;i++)//所有的起点
{
for(int j=0;j<endPoint.CastStep[i];j++)//一个起点的步数
{
p = *endPoint.ascending[i];
temp = j + abs(p.x - Kin.x) + abs(p.y - Kin.y);//遇到骑士则和骑士一起跳
if(temp < GoodSteps)
GoodSteps = temp;
}
}
return GoodSteps;
}
point* GetCanGo(point nowPoint,int SumSteps)//得到下一步可以走的点
{
count = 0;
point temp[8];//最多8个点
if((nowPoint.x-1 >= 0 && nowPoint.y+2 < cells) && (Chessboard[nowPoint.x-1][nowPoint.y+2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-1][nowPoint.y+2].CastStep[index]))
{
count++;
temp[0].x = nowPoint.x-1;
temp[0].y = nowPoint.y+2;
}
else
temp[0].x = -1;//为了标记用
if((nowPoint.x-1 >= 0 && nowPoint.y-2 > 0) && (Chessboard[nowPoint.x-1][nowPoint.y-2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-1][nowPoint.y-2].CastStep[index]))
{
count++;
temp[1].x = nowPoint.x-1;
temp[1].y = nowPoint.y-2;
}
else
temp[1].x = -1;//为了标记用
if((nowPoint.x+1 < rows && nowPoint.y+2 < cells) && (Chessboard[nowPoint.x+1][nowPoint.y+2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+1][nowPoint.y+2].CastStep[index]))
{
count++;
temp[2].x = nowPoint.x+1;
temp[2].y = nowPoint.y+2;
}
else
temp[2].x = -1;//为了标记用
if((nowPoint.x+1 < rows && nowPoint.y-2 >= 0) && (Chessboard[nowPoint.x+1][nowPoint.y-2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+1][nowPoint.y-2].CastStep[index]))
{
count++;
temp[3].x = nowPoint.x+1;
temp[3].y = nowPoint.y-2;
}
else
temp[3].x = -1;//为了标记用
if((nowPoint.x+2 < rows && nowPoint.y+1 < cells) && (Chessboard[nowPoint.x+2][nowPoint.y+1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+2][nowPoint.y+1].CastStep[index]))
{
count++;
temp[4].x = nowPoint.x+2;
temp[4].y = nowPoint.y+1;
}
else
temp[4].x = -1;//为了标记用
if((nowPoint.x+2 < rows && nowPoint.y-1 >= 0) && (Chessboard[nowPoint.x+2][nowPoint.y-1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+2][nowPoint.y-1].CastStep[index]))
{
count++;
temp[5].x = nowPoint.x+2;
temp[5].y = nowPoint.y-1;
}
else
temp[5].x = -1;//为了标记用
if((nowPoint.x-2 >= 0 && nowPoint.y+1 < cells) && (Chessboard[nowPoint.x-2][nowPoint.y+1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-2][nowPoint.y+1].CastStep[index]))
{
count++;
temp[6].x = nowPoint.x-2;
temp[6].y = nowPoint.y+1;
}
else
temp[6].x = -1;//为了标记用
if((nowPoint.x-2 >= 0 && nowPoint.y-1 >= 0) && (Chessboard[nowPoint.x-2][nowPoint.y-1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-2][nowPoint.y-1].CastStep[index]))
{
count++;
temp[7].x = nowPoint.x-2;
temp[7].y = nowPoint.y-1;
}
else
temp[7].x = -1;//为了标记用
point* re = (point*)malloc(sizeof(point) * count);
int t = 0;
for(int i=0;i<8;i++)
{
if(temp[i].x != -1)
{
re[t] = temp[i];
t++;
}
}
return re;
}
#include <stdlib.h>
#include <time.h>
#include <math.h>
//先还是让每个起点走遍整个棋盘,不过这里不光去记录步数了,还要记录路径才行,因为国王可能会和骑士想遇,
//再国王去“访问”最佳聚会位置,计算所需要的步数,再访问第二佳的位置,到某个位置时会出现到它的步数和(不包国王的跳步)
//都要大于后面的包括国王在内的位置的和,这就可以返回了^_^
//记录路径最新办法:在每一个点上添加一个指针指向它的上一个点,哈哈最后的会聚点必然可以逆着找到跳到它这里的一条完整的路径
struct point
{
int x;
int y;
int* CastStep;
point** ascending;//保存上一个点
};
point* GetCanGo(point,int);
void Walk(point,int);
int KinVisit(point);
int index = 0;//当前的起点下标
int rows = 0;
int cells = 0;
point** Chessboard;
point* StartPoint;
point Kin;
int StartNum = 0;
void main()
{
printf("欢迎使用神奇的棋盘(国王版)^_^\n");
printf("输入棋盘的行数:");
scanf(" %d",&rows);
printf("输入棋盘的列数:");
scanf(" %d",&cells);
printf("您使用了%d X %d的棋盘,输入的座标x必须在0-%d之间 y必须在0-%d之间\n",rows,cells,rows-1,cells-1);
Chessboard = (point**)malloc(4*rows);
for(int e=0;e<rows;e++)
{
Chessboard[e] = (point*)malloc(sizeof(point)*cells);
}
printf("请输入起点个数:");
scanf("%d",&StartNum);
for(int i=0;i<rows;i++)//初始化棋盘
{
for(int j=0;j<cells;j++)
{
Chessboard[i][j].x = i;
Chessboard[i][j].y = j;
Chessboard[i][j].CastStep = (int*)malloc(4 * StartNum);
Chessboard[i][j].ascending = (point**)malloc(4 * StartNum);
for(int a=0;a<StartNum;a++)
Chessboard[i][j].CastStep[a] = 0;
}
}
StartPoint = (point*)malloc(sizeof(point)*StartNum);
for(int k=0;k<StartNum;k++)
{
printf("输入第%d个起点的座标\nx=",k+1);
scanf("%d",&StartPoint[k].x);
printf("y=");
scanf("%d",&StartPoint[k].y);
}
printf("输入国王座标:\nx=");
scanf("%d",&Kin.x);
printf("y=");
scanf("%d",&Kin.y);
printf("必须信息读取完毕!\n计算中");
long start = clock();//开始计时
for(index=0;index<StartNum;index++)//让每个起点走遍整个棋盘
{
Walk(StartPoint[index],0);
}
int CastSteps = 0;
int CastDays = 0;
point LastPoint;
for(int a=0;a<rows;a++)//这里开始搜索最佳聚会地点了
{
for(int b=0;b<cells;b++)
{
int sum=0;
int max=0;
for(int c=0;c<StartNum;c++)
{
sum += Chessboard[a][b].CastStep[c];//统计总步数
if(Chessboard[a][b].CastStep[c] > max)//寻找最大的步数
max = Chessboard[a][b].CastStep[c];
}
int te = KinVisit(Chessboard[a][b]);//得到国王到达需要的最少步数
if(te > max)
max = te;
sum += te;
if(CastSteps >= sum && CastDays >= max)
{
CastSteps = sum;
CastDays = max;
LastPoint = Chessboard[a][b];
continue;
}
if(CastSteps == 0)
{
CastSteps = sum;
CastDays = max;
LastPoint = Chessboard[a][b];
}
}
}
long end = clock();//结束计时
printf("\n计算完毕,用时:%ld毫秒\n会聚地点:(%d,%d)\n需要的时间:%d天\n所有人总共花去时间:%d天\n",end-start,LastPoint.x,LastPoint.y,CastDays,CastSteps);
printf("输入任意字符退出..");
char c;
scanf(" %c",&c);
}
int count = 0;//保存下一次能走的点的个数
void Walk(point nowPoint,int SumSteps)
{
Chessboard[nowPoint.x][nowPoint.y].CastStep[index] = SumSteps;
point* NextCanGo = GetCanGo(nowPoint,++SumSteps);//在这里累加的注意咯
int num = count;
for(int i=0;i<num;i++)
{
Chessboard[NextCanGo[i].x][NextCanGo[i].y].ascending[index] = &nowPoint;//在这里记录上一个位置
Walk(NextCanGo[i],SumSteps);
}
}
int KinVisit(point endPoint)//国王出发访问咯,返回最佳步数
{
int GoodSteps = abs(endPoint.x - Kin.x) + abs(endPoint.y - Kin.y);//无疑这是最大的情况
int temp = 0;
point p;
for(int i=0;i<StartNum;i++)//所有的起点
{
for(int j=0;j<endPoint.CastStep[i];j++)//一个起点的步数
{
p = *endPoint.ascending[i];
temp = j + abs(p.x - Kin.x) + abs(p.y - Kin.y);//遇到骑士则和骑士一起跳
if(temp < GoodSteps)
GoodSteps = temp;
}
}
return GoodSteps;
}
point* GetCanGo(point nowPoint,int SumSteps)//得到下一步可以走的点
{
count = 0;
point temp[8];//最多8个点
if((nowPoint.x-1 >= 0 && nowPoint.y+2 < cells) && (Chessboard[nowPoint.x-1][nowPoint.y+2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-1][nowPoint.y+2].CastStep[index]))
{
count++;
temp[0].x = nowPoint.x-1;
temp[0].y = nowPoint.y+2;
}
else
temp[0].x = -1;//为了标记用
if((nowPoint.x-1 >= 0 && nowPoint.y-2 > 0) && (Chessboard[nowPoint.x-1][nowPoint.y-2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-1][nowPoint.y-2].CastStep[index]))
{
count++;
temp[1].x = nowPoint.x-1;
temp[1].y = nowPoint.y-2;
}
else
temp[1].x = -1;//为了标记用
if((nowPoint.x+1 < rows && nowPoint.y+2 < cells) && (Chessboard[nowPoint.x+1][nowPoint.y+2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+1][nowPoint.y+2].CastStep[index]))
{
count++;
temp[2].x = nowPoint.x+1;
temp[2].y = nowPoint.y+2;
}
else
temp[2].x = -1;//为了标记用
if((nowPoint.x+1 < rows && nowPoint.y-2 >= 0) && (Chessboard[nowPoint.x+1][nowPoint.y-2].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+1][nowPoint.y-2].CastStep[index]))
{
count++;
temp[3].x = nowPoint.x+1;
temp[3].y = nowPoint.y-2;
}
else
temp[3].x = -1;//为了标记用
if((nowPoint.x+2 < rows && nowPoint.y+1 < cells) && (Chessboard[nowPoint.x+2][nowPoint.y+1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+2][nowPoint.y+1].CastStep[index]))
{
count++;
temp[4].x = nowPoint.x+2;
temp[4].y = nowPoint.y+1;
}
else
temp[4].x = -1;//为了标记用
if((nowPoint.x+2 < rows && nowPoint.y-1 >= 0) && (Chessboard[nowPoint.x+2][nowPoint.y-1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x+2][nowPoint.y-1].CastStep[index]))
{
count++;
temp[5].x = nowPoint.x+2;
temp[5].y = nowPoint.y-1;
}
else
temp[5].x = -1;//为了标记用
if((nowPoint.x-2 >= 0 && nowPoint.y+1 < cells) && (Chessboard[nowPoint.x-2][nowPoint.y+1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-2][nowPoint.y+1].CastStep[index]))
{
count++;
temp[6].x = nowPoint.x-2;
temp[6].y = nowPoint.y+1;
}
else
temp[6].x = -1;//为了标记用
if((nowPoint.x-2 >= 0 && nowPoint.y-1 >= 0) && (Chessboard[nowPoint.x-2][nowPoint.y-1].CastStep[index] == 0
|| SumSteps < Chessboard[nowPoint.x-2][nowPoint.y-1].CastStep[index]))
{
count++;
temp[7].x = nowPoint.x-2;
temp[7].y = nowPoint.y-1;
}
else
temp[7].x = -1;//为了标记用
point* re = (point*)malloc(sizeof(point) * count);
int t = 0;
for(int i=0;i<8;i++)
{
if(temp[i].x != -1)
{
re[t] = temp[i];
t++;
}
}
return re;
}
posted on 2008-06-05 10:40 Handsome Kun 阅读(433) 评论(0) 编辑 收藏 举报