ACM习题-有趣的问题

该问题探讨如何找到穿过一个包含垂直墙壁和门道的房间的最短路径。初始点为(0,5),终点为(10,5)。题目提供挡板位置信息,需要通过数学分析找出最佳路线。程序实现中,输入包含挡板信息,输出最短路径长度,例如在给定示例中,最短路径长度为10.00和10.06。" 106357805,5714615,C# WinForm中TreeView控件实现父子级别递归显示,"['C#编程', 'GUI开发', '数据库交互', 'WinForm控件', '事件驱动']

描述

  You are to find the length of the shortest path through a chambercontaining obstructing walls. The chamber will always have sides at x = 0, x =10, y = 0, and y = 10. The initial and final points of the path are always (0,5) and (10, 5). There will also be from 0 to 18 vertical walls inside thechamber, each with two doorways. The figure below illustrates such a chamberand also shows the path of minimal length. 一个人

简要描述:一个人要从一个屋子里出去,屋子里有挡板,如上图在横坐标4处有0-2,7-8,9-10三个挡板,在横坐标为7处有0-3,4.5-6,7-10三个挡板,人从坐标(0,5)处出发,到(10,5)处出去,求经历的最短距离。


思路:这是纯数学分析,比较简单,只要判断出人要从那个位置出去就行了。

直接程序如下:

<span style="font-size:18px;"><strong>#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <cmath>

using namespace std;

int main()
{
    float a[100]={0};
    int i,j;
    int num;            //墙的数目;
    float x,high;       //x保存每一次出去点的横向坐标,high为出点的纵向坐标;
    double sum;         //记录总距离;
    float k1,k2,c;      
    bool flag=false;
    while(cin>>num && num!=-1)
	{
		fflush(stdin);
		sum=0.0;x=0;high=5;
		for(i=0;i<num*5;i++)
		{
			cin>>a[i];     //每组输入5个数,第一个为墙的横坐标,另外四个为挡板的纵向坐标;              
		}
		for(i=0;i<num;i++)
		{
			j=i*5;
			if(((a[j+1]<high)&&(a[j+2]>high))||((a[j+3]<high)&&(a[j+4]>high))) //直线通过;
			{
				flag=true;
			}
			else if(a[j+1]>high)   //直线通过撞到第一块挡板;
			{
				if(flag)         //若上一次是直线通过;
				{
					c=a[j];      
				}
				else
				{
					c=a[j]-x;       
                }
				k1=a[j+1]-high;     
				sum+=sqrt(c*c+k1*k1);    //得到本次通过挡板时经过的最小距离;
				high=a[j+1];
				x=a[j];
				flag=false;
			}
			else if((a[j+2]<high) && (a[j+3]>high))  //直线通过撞到第二块挡板;
			{
				if(flag)
				{
					c=a[j];
				}
				else
				{
					c=a[j]-x;
                }
				k1=high-a[j+2];
				k2=a[j+3]-high;
				if(k1>=k2)                //判断是从第一块挡板的上部出去,还是从第二块挡板的下部出去;
				{
					sum+=sqrt(c*c+k2*k2);
					high=a[j+3];
				}
				else
				{
					sum+=sqrt(c*c+k1*k1);
					high=a[j+2];
				}
				x=a[j];
				flag=false;
			} 
			else if(a[j+4]<high)     //直线通过撞到第三块挡板;
			{
				if(flag)
				{
					c=a[j];
				}
				else
				{
					c=a[j]-x;
                }
				k1=high-a[j+4];
				c=a[j]-x;
				sum+=sqrt(c*c+k1*k1);
				high=a[j+4];
				x=a[j];
				flag=false;
			}                                                                     
		}
		if(high==5)      //最后沿直线出去;
		{
			c=10-x;
			sum+=c;
		}
		else             //若是沿斜线出去,判断上一次出点纵坐标与5的大小;
		{
			c=10-x;
			if(high>5)
			{
				k1=high-5;
			}
			else
			{
				k1=5-high;
			}
			sum+=sqrt(k1*k1+c*c);
        }
		printf("%.2f\n",sum);
	}
    system("pause");
    return 0;
}
</strong></span>

输入:

1

5 4 6 7 8

2

4 2 7 8 9

7 3 4.5 6 7

-1

输出:

10.00

10.06


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值