您的位置:首页 > 编程语言 > C语言/C++

《程序员》算法擂台之骑士聚会问题(c语言版) 二

2008-06-05 10:40 417 查看


很明显,思考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;

}

思考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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐