TOJ 3817 Matchsticks

  原题链接:http://acm.tju.edu.cn/toj/showp3817.html

  第一次上toj做题,今天开始感觉这个题想仔细点应该是不难的。但是写好了以后上去直接攒了七八个wa,怎么想也想不出哪儿错了。直接搜解题报告也没有。因为是今天新出的题吧。晚上几乎使上了各种手段包括各种外援后终于知道哪儿错了。费劲九牛二虎之力改完后ac,真的是折磨人啊。这种BT模拟题是最要命的。

  下面讲一下这个题的解法,给一些棍子,摆出最大数和最小数。很容易想到最大就是位数尽量多的情况下,每位的数值尽量大。最小就是相反。求最大数很好求,因为只要摆尽量多的1,如果不是偶数,就摆一个7,再加余下的1。把最小数就比较麻烦。首先确定最多有多少位,如果是7的倍数则有n/7位,每位是8。如果n小于7,则直接输出一位数,就是最小的。这两种是简单的情况。

  一般的情况是把一堆棍子分成两堆,一堆是7的倍数,一堆是除以7的余数。两步处理:

  (1)如果余数为1,则把1和一个8换成2根和6根,不然就直接把第一位置成需要棍数k的那个最小的数。

  (2)从前往后变换,如果和8相邻的那一位能和8一起换位两位两位更小的数则变换,直到没有8或者不能变换为止。

#include<iostream>
using namespace std;
//最小的数位数尽可能少的情况下,数值尽量小
//最大数位数尽可能多的情况下,数字尽量大
int main()
{
	int n[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
	int tot, x, d, k, flag, t, i;
	scanf("%d", &tot);
	while (tot--)
	{
		scanf("%d", &x);
		if (x <= 7)//小于等于7时最小的就是一位数
		{
			for (int i = 1; i < 10; i++)
				if (x == n[i])
				{
					printf("%d ", i);
					break;
				}
		}
		else {
			//想法就是先转换成位数最少的数
			//然后从前往后把相邻的两位替换成棍数一样数值却小的两位数
			k = x / 7;
			d = x %  7;
			if (d)
			{
				int tem;
				if (d == 1)tem = 9;
				else 
					for (int i = 1; i < 10; i++)
						if (d == n[i])
						{
							tem = i;
							break;
						}
				bool r = true;//如果是第一位,不能为0
				while (k)
				{
					bool flag = true;
					if (r) i = 1;
					else i = 0;
					r = false;
					for (i; i <= tem; i++)
					{
						for (int j = 0; j < 8; j++)
							if (n[i] + n[j] == d + n[8])
							{
								printf("%d", i);
								tem = j;
								flag = false;
								k--;
								break;
							}
						if (!flag)break;
					}
					if (flag)//如果没有找到,直接退出
					{
						printf("%d", tem);
						break;
					}
					d = n[tem];//没有退出则继续
					if (!k)//如果已经到了最后一位则不再循环
					{
						printf("%d", tem);
						break;
					}
				}
			}
			for (int i = 0; i < k; i++)
				printf("8");
			printf(" ");
		}
		//打印最大位比较简单
		k = x / 2;
		t = x % 2;
		if (t)
		{
			printf("7");
			k--;
		}
		for (int i = 0; i < k; i++)
			printf("1");
		printf("\n");
	}
	return 0;
}
posted @ 2011-02-20 22:45  like@neu  阅读(318)  评论(0编辑  收藏  举报