Handsome Kun

仰天长笑,笑天下可笑之人; 大肚能盛,盛天下可盛之事!

导航

《程序员》算法擂台之骑士聚会问题(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;
}

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

posted on 2008-06-05 10:40  Handsome Kun  阅读(433)  评论(0编辑  收藏  举报