POJ2584 T-Shirt Gumbo【二分图多重匹配】

题目意思是参赛队员要选择队服,队伍的尺寸有5中,S,M,L,X,T

每个人的衣服的尺寸有个接受范围,在这个范围内的衣服都可以接受。

现在每个尺寸的服装有数量限制,但我们要尽可能要让队员拿到服装。

如果每个人都可以拿到符合要求的服装就输出T-shirts rock!

否则就输出I'd rather not wear a shirt anyway...

 

输入看上去很复杂,先输入start,再输入参赛人员的个数。

然后输入每个人的服装接受范围,再接着输入每种尺寸服装的数量

接下来输入END

输入ENDINPUT结束输入。

 

这道题目可以用有点像二分图匹配,但二分图匹配是一对一的,这道题目可以说是一对多

但是我们可以做一点处理,用二分图匹配的匈牙利算法思想。

解题思路,将匈牙利算法中cy变成二维,cy【i】【j】表示第i种服装第j件被选走

Numy【i】的值a表示如果第i种服装被选走,那就是第a件被拿走

这是代码中比较关键的地方。

 

还有一种想法,我还没实现。

因为这道题目的数据比较小,我们可以把每一件衣服都看成独一无二的衣服,这样就变成了一对多的二分图最大匹配。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<functional>
#include<algorithm>
#define maxn 35
using namespace std;
int maps[maxn][maxn];//邻接矩阵
int cy[maxn][maxn];//点集合Y选中情况
int vis[maxn];
int numy[maxn],limit[maxn];//每种衣服的数量
char s[maxn],a,b;
int n;

int path(int u)//找增广路
{
	int i,j;
	for( i=1;i<=5;i++)
	{
		if(maps[u][i]&&!vis[i])
		{
			vis[i]=1;
			if(numy[i]<limit[i])//其实就是匈牙利算法第二个if语句
			{
				cy[i][numy[i]++]=u;
				return 1;
			}
			else//增广
			{
				for( j=0;j<limit[i];j++)
					if(path(cy[i][j]))//尝试让这件衣服的主人换件衣服
					{
						cy[i][j]=u;
						return 1;
					}
			}
		}
	}
	return 0;
}
void MulMatch()
{
	int ans=0;
	memset(cy,0,sizeof(cy));
	memset(numy,0,sizeof(numy));
	for(int i=1;i<=n;i++)
	{
		memset(vis,0,sizeof(vis));
		ans+=path(i);
	}
	if(ans==n)
		printf("T-shirts rock!\n");
	else
		printf("I'd rather not wear a shirt anyway...\n");
}
int change(char c)
{
	if(c=='S')
		return 1;
	else if(c=='M')
		return 2;
	else if(c=='L')
		return 3;
	else if(c=='X')
		return 4;
	else if(c=='T')
		return 5;
}
int main()
{
	int i,j;
	int st,ed;
	while(scanf("%s",&s)!=EOF)
	{
		if(strcmp(s,"ENDOFINPUT")==0)
			break;
		scanf("%d",&n);
		getchar();
		memset(maps,0,sizeof(maps));
		for(i=1;i<=n;i++)
		{
			scanf("%c%c",&a,&b);
			getchar();
			printf("%c %c\n",a,b);
			st=change(a);
			ed=change(b);
			printf("st=%d ed=%d\n",st,ed);
			for(j=st;j<=ed;j++)
				maps[i][j]=1;
		}
		for(i=1;i<=5;i++)
			scanf("%d",&limit[i]);
		scanf("%s",&s);
		MulMatch();
	}
	return 0;
}


1. 内容概要 本项目是一个支持科学函数的命令行计算器,兼容 C++98 标准。它实现了中缀表达式词法分析、后缀表达式转换与求值,支持常见数学运算(如幂、三角函数、对数等)与括号优先级解析。程序还提供了角度版三角函数、角度与弧度互转功能,并支持函数调试输出与函数演示模式。 2. 适用人群 * C++ 初中级学习者,特别是希望深入理解表达式求值机制者 * 需要一个可扩展的计算引擎的项目开发者 * 想通过项目实践词法分析、调度场算法、数学函数封装的开发者 * 高校学生课程设计、编译原理实践者 3. 使用场景及目标 * 实现中缀表达式的完整求解器,支持函数嵌套、优先级与结合性处理 * 提供角度与弧度版本的三角函数,以适应不同输入偏好 * 演示中缀转后缀过程,辅助编程教育与算法教学 * 提供科学函数辅助计算,如 `log`, `sqrt`, `abs`, `exp`, `ceil`, `floor` 等 4. 其他说明 * 支持函数:sin, cos, tan(弧度);sind, cosd, tand(角度) * 支持函数嵌套,如 `sin(deg2rad(30))` * 支持操作符:+, -, \*, /, ^, \*\*(幂运算)与括号优先级 * 所有函数均通过 map 注册,方便扩展与自定义 * 输入 `help` 查看支持函数,`demo` 观看转后缀过程,`quit` 退出程序 * 提示用户避免使用 `°` 符号,推荐使用角度函数代替 * 可通过 `g++ calculator.cpp -o calculator -lm` 编译(需链接数学库)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值