模拟题poj1016-Numbers That Count
模拟题一定要有清晰的思路,不要轻易的开始敲代码,仔细分析题目。最好在做之前先用自己的方法把解题的大致结构手写下来
大致题意:
题意不难懂,对于任意的数字串n,都可以压缩存储为
c1 d1 c2 d2 .... ck dk 形式的数字串
而存在一些特别的数字串,其压缩前后的样子是一模一样的
定义这种数字串为self-inventorying
当我们把n看成原串,
A为n压缩1次后的数字串,
B为n压缩2次后的数字串(即A压缩1次后的数字串)
....以此类推
K为n压缩k次后的数字串(即K-1压缩k-1次后的数字串)
则可以延伸出数字串n的3种属性:
1、 n压缩1次就马上出现self-inventorying特性,即 n n n n n n n .....
2、 n压缩j次后的数字串J出现self-inventorying特性,即 n A B C....H I J J J J J J J
3、 n压缩j次后的数字串J,每再压缩K次,重新出现数字串J,即n A B... J ..K J ..K J..K J
其中K称为循环间隔,K>=2
现给定一字符串,输出其属性。 属性1优于属性2,属性2优于属性3;
当且仅当n的3种属性都不存在时,n can not be classified after 15 iterations
解题思路:
字符串处理,纯粹的模拟题
压缩n时要注意,ck可能是1位,也可能是2位,需要判断。
设R(n)为描述整数n的压缩数字串
#include<stdio.h>
#include<string.h>
/*该函数用于压缩字符串n,并把压缩后的结果给t*/
void R(char *n,char *t)
{
int i,j;
int time[10]={0};//记录0~9每个数字出现的次数
for(i=0;i<strlen(n);i++)
time[n[i]-'0']++;
for(i=0,j=0;i<10;i++)
{
if(time[i])
{
/*因为n最长只有80个字符,所以time最大不超过两位数,所以分两种情况*/
if(time[i]>0&&time[i]<=9)
{
t[j++]=time[i]+'0';
t[j++]=i+'0';
}
if(time[i]>=10)
{
t[j++]=time[i]/10+'0';
t[j++]=time[i]%10+'0';
t[j++]=i+'0';
}
}
}
t[j]='\0';
}
int main()
{
char n[16][100];
int i,j;
while(scanf("%s",n[0])!=EOF)
{
if(strcmp(n[0],"-1")==0) break;//n[0]就是原字符串
int flag1=0; //属性1,n is self-inventorying
int flag2=0; //属性2,n is self-inventorying after j steps,顺便记录j
int flag3=0; //属性3,n is enters an inventory loop of length k,顺便记录k
for(i=1;i<=15;i++) //把数字串n[0]压缩15次
R(n[i-1],n[i]);
if(strcmp(n[0],n[1])==0) //属性1判断,n压缩1次就是其本身
flag1=1;
if(flag1==0)
{
for(j=1;j<15;j++)
{
if(strcmp(n[j],n[j+1])==0) //属性2判断,n压缩j次后的数字串n[j]具有属性1
{
flag2=j;
break;
}
}
if(flag2==0)
{
for(j=1;j<=15;j++) //属性3判断,两两枚举各次压缩的数字串,注意循环间隔>=2
{
for(i=0;i<=j-2;i++)
{
if(strcmp(n[j],n[i])==0)
{
flag3=j-i;
break;
}
}
if(flag3!=0)
break;
}
}
}
printf("%s",n[0]);
if(flag1!=0)
printf(" is self-inventorying\n");
else if(flag2!=0)
printf(" is self-inventorying after %d steps\n",flag2);
else if(flag3!=0)
printf(" enters an inventory loop of length %d\n",flag3);
else
printf(" can not be classified after 15 iterations\n");
}
return 0;
}