Door Man poj 1300

     题目大意: 沿着一个通道,穿过这些大房间,并把房门关上。你的问题是能否找到一条路径经过所有开着门的房间,并使得:
1)  通过门后立即把门关上;
2)  关上了的门不再打开;
3)  最后回到你自己的房间(房间0),并且所有的门都已经关闭了。

 

    分析:本题实际上是判断一个图中是否存在欧拉回路或欧拉通路,要分两种情况考虑:
1)如果所有的房间都有偶数个门(通往其他房间),那么有欧拉回路,可以从0号房间出发,回到0号房间。但是这种情况下,出发的房间必须为0,因为要求回到0号房间。例如,第1个测试数据所对应的图为图5.6(a),图中有浅色阴影的顶点(即顶点0),表示管家初始时所处的房间;在该测试数据中,管家可以回到0号房间。


2)有两个房间的门数为奇数,其余的都是偶数,如果出发的房间和0号房间的门数都是奇数,那么也可以从出发的房间到达0号房间,并且满足题目要求。但是不能从房间0出发,必须从另一个门数为奇数的房间出发。例如第2、3个测试数据就是这种情形,对应的图为图(b)和图(c),输出的结果分别是"NO"和"YES 7"。

 

   本题的难点在于输入数据的处理:
1)  因为有空行,而且这些空行都是有用的信息。由于有空行,所以不能简单地用cin读入每个房间有门通往其他房间的房间号;

2)  一行数据中既有字符型数据,又有数值型数据。比如START 1 2,必须区分不同类型的数据。

因此,必须采用cin.getline函数或者getchar函数将输入数据读入到字符数组buf中,再采用sscanf函数从buf中读出有用的数据。

sscanf()函数的用法:

                http://blog.csdn.net/hearthougan/article/details/14054415

 

 

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>

using namespace std;

int readLine( char *s )//以字符形式读入每行数据并返回字符串的长度
{
	int L;
	for(L = 0; ( s[L] = getchar() ) != '\n' && s[L] != EOF; ++L)
		;
	s[L] = 0;
	return L;
}

int main()
{
	int i, j;
	char buf[128];
	int M, N;//M为管家的起始房间号,N为房间总数
	int door[20];//记录每个房间的门数

	while( readLine( buf ) )
	{
		if(buf[0] == 'S')
		{
			sscanf( buf, "%*s %d %d", &M, &N);
			memset(door, 0, sizeof(door));

			int doors = 0;//存放门的总数目
			for(i = 0; i < N; ++i)
			{
				readLine( buf );
				int k = 0;//读取数据的起始位置
				//读取每个房间有门通往其他房间的房间号
				while( sscanf(buf+k, "%d", &j) == 1 )
				{
					doors++;
					door[i]++;
					door[j]++;
				//	cout<<"*************"<<endl;
				//	cout<<"door["<<i<<"] = "<<door[i]<<" door["<<j<<"] = "<<door[j]<<endl;
				//	cout<<"buf["<<k<<"] = "<<buf[k]<<endl;
				//	cout<<"*************"<<endl;
					while( buf[k] && buf[k] !=' ' )
						k++;
				//	cout<<"*************"<<endl;
				//	cout<<"buf["<<k<<"] = "<<buf[k]<<endl;
				//	cout<<"*************"<<endl;
					while( buf[k] && buf[k] == ' ' )
						k++;
				}
			}
			readLine( buf );//读入"END"
			int odd = 0, even = 0;//odd奇点的个数,even偶点的个数
			for(i = 0; i < N; ++i)
			{
				if(door[i] % 2 == 0)
					even++;
				else
					odd++;
			}
				if(odd == 0 && M == 0)
					cout<<"YES "<<doors<<endl;
				else if(odd == 2 && door[M] % 2 == 1 && door[0] % 2 == 1 && M != 0)
					cout<<"YES "<<doors<<endl;
				else 
					cout<<"NO"<<endl;
		}
		else if( !strcmp(buf, "ENDOFINPUT") )
			break;
	}
	system("pause");
	return 0;
}

/**

START 1 2
1

END
START 0 5
1 2 2 3 3 4 4




END
START 0 10
1 9
2
3
4
5
6
7
8
9

END
ENDOFINPUT

*/


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值