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;
}
浙公网安备 33010602011771号