POJ-1010-STAMPS

// Input: STAMPS{TYPES 0}\nCUSTOMERS{NUMS 0}\n
// Output: CUTSOMER_NUM (TYPE_NUM):{ TYPES | tie} | ---- none
//   max_type_num == 4,fewest TYPE_NUM best, the with highest single-value best
// Method: 
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <memory.h>

// STRUCTS
struct SSTAMPS
{
	int types[100];
	int num;
};
struct SCUSTOMERS
{
	int totals[100];
	int num;
};
struct SOUTPUT
{
	int total;
	int types[100];
	int typeIndices[100];
	int num;
	int tie;
	int typeNum;
};

// VARS
SOUTPUT tempOutput;
int buf[100];
int bufIndices[100];

// FUNCS
// read infos(stamps and customers)
bool readInfos(SSTAMPS *stamps, SCUSTOMERS *customers)
{
	// reset		
	stamps->num = 0;
	customers->num = 0;

	// read stamps	
	while (scanf("%d", &stamps->types[stamps->num]) != EOF) 
	{
		if (!stamps->types[stamps->num])
			break;
		stamps->num ++;
	}
	if (!stamps->num)
		return false;
	
	// read customers
	while (scanf("%d", &customers->totals[customers->num]) != EOF)
	{
		if (!customers->totals[customers->num])
			break;
		customers->num ++;
	}

	return true;
}

// check outputs
void checkOutputs(SOUTPUT *cur, SOUTPUT *temp, int *types, int num)
{
	// count type num
	temp->typeNum = 0;	
	int i, j;
	memset(buf, 0, sizeof(int) * temp->num);
	for (i = 0; i < temp->num-1; ++i)
	{
		if (buf[i] == 1)
			continue;
		temp->typeNum ++;
		for (j = i+1; j < temp->num; ++j)
		{
			if (temp->typeIndices[i] == temp->typeIndices[j])
			{
				buf[j] = 1;
			}
		}
	}
	if (!buf[i])
		temp->typeNum ++;

	// compare
	bool better = false;
	// more type num OR  OR 
	if (temp->typeNum > cur->typeNum)
	{
		better = true;
	}
	// less stamp num
	else if (temp->typeNum == cur->typeNum && temp->num < cur->num)
	{
		better = true;
	}
	// bigger max one
	else if (temp->typeNum == cur->typeNum && temp->num == cur->num && temp->types[0] > cur->types[0])
	{
		better = true;
	}
	// tie
	else if (temp->typeNum == cur->typeNum && temp->num == cur->num && temp->types[0] == cur->types[0])
	{		
		for (i = 0; i < temp->num; ++i)
		{
			buf[i] = temp->types[i];
			bufIndices[i] = temp->typeIndices[i];
		}
		// sort
		for (i = 0; i < temp->num-1; ++i)
		{
			for (j = i+1; j < temp->num; ++j)
			{
				if (buf[j] > buf[i])
				{
					int data = buf[j];
					buf[j] = buf[i];
					buf[i] = data;
					data = bufIndices[j];
					bufIndices[j] = bufIndices[i];
					bufIndices[i] = data;
				}
				else if (buf[j] == buf[i] && bufIndices[j] < bufIndices[i])
				{
					int data = bufIndices[j];
					bufIndices[j] = bufIndices[i];
					bufIndices[i] = data;
				}
			}
		}

		// check equal cur
		bool equalCur = true;
		for (i = 0; i < temp->num; ++i)
		{
			if (bufIndices[i] != cur->typeIndices[i])
			{
				equalCur = false;
				break;
			}
		}
		if (equalCur)
			return;

		cur->tie = 1;
	}

	// if better copy temp to cur
	if (better)
	{
		cur->tie = 0;
		cur->num = temp->num;
		cur->typeNum = temp->typeNum;
		for (int i = 0; i < temp->num; ++i)
		{
			cur->types[i] = temp->types[i];
			cur->typeIndices[i] = temp->typeIndices[i];
		}
	}
}

// get best division, 
int getBestDivision(SOUTPUT *output, int curRet, int *types, int num, int total)
{
	// end condition
	if (curRet > 4 || total < 0 || (curRet == 4 && total))
		return 0;	
	if (!total)
	{
		tempOutput.num = curRet;		
		return 1;
	}

	// go through types from bigger one to smaller one
	for (int i = 0; i < num; ++i)
	{
		tempOutput.types[curRet] = types[i];
		tempOutput.typeIndices[curRet] = i;
		if (getBestDivision(output, curRet+1, types, num, total - types[i]))
		{
			checkOutputs(output, &tempOutput, types, num);
		}
	}

	return 0;
}

// divide customers' total, output the list
void divide(SOUTPUT *output, SSTAMPS *stamps, int total)
{
	output->total = total;
	// reset
	output->num = 0;
	output->tie = 0;
	output->typeNum = 0;

	// sort 
	int i, j;
	for (i = 0; i < stamps->num-1; ++i)
	{
		for (j = i+1; j < stamps->num; ++j)
		{
			if (stamps->types[j] > stamps->types[i])
			{
				int temp = stamps->types[i];
				stamps->types[i] = stamps->types[j];
				stamps->types[j] = temp;
			}
		}
	}

	// reset temp output
	tempOutput.num = 0;
	tempOutput.tie = 0;
	tempOutput.typeNum = 0;

	// get division
	getBestDivision(output, 0, stamps->types, stamps->num, total);
}

// output
void outputLine(SOUTPUT *output)
{
	if (output->num > 0)
	{
		printf("%d (%d):", output->total, output->typeNum);
		// normal
		if (!output->tie)
		{
			for (int i = output->num-1; i >= 0; --i)
			{
				printf(" %d", output->types[i]);
			}
			printf("\n");
		}
		// tie
		else
		{
			printf(" tie\n");
		}
	}
	// none
	else if (!output->num)
	{
		printf("%d ---- none\n", output->total);
	}
}

// solve
void solve(SSTAMPS *stamps, SCUSTOMERS *customers)
{
	SOUTPUT output;	
	for (int i = 0; i < customers->num; ++i)
	{
		divide(&output, stamps, customers->totals[i]);
		outputLine(&output);
	}
}

#define LOCAL
int main()
{
#ifdef LOCAL 
	freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
#endif

	SSTAMPS stamps;
	SCUSTOMERS customers;

	while (readInfos(&stamps, &customers))
	{
		solve(&stamps, &customers);
	}

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值