POJ1016 Numbers That Count ,<vector>

题目:

Numbers That Count

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 21991 Accepted: 7410

Description

"Kronecker's Knumbers" is a little company that manufactures plastic digits for use in signs (theater marquees, gas station price displays, and so on). The owner and sole employee, Klyde Kronecker, keeps track of how many digits of each type he has used by maintaining an inventory book. For instance, if he has just made a sign containing the telephone number "5553141", he'll write down the number "5553141" in one column of his book, and in the next column he'll list how many of each digit he used: two 1s, one 3, one 4, and three 5s. (Digits that don't get used don't appear in the inventory.) He writes the inventory in condensed form, like this: "21131435". 

The other day, Klyde filled an order for the number 31123314 and was amazed to discover that the inventory of this number is the same as the number---it has three 1s, one 2, three 3s, and one 4! He calls this an example of a "self-inventorying number", and now he wants to find out which numbers are self-inventorying, or lead to a self-inventorying number through iterated application of the inventorying operation described below. You have been hired to help him in his investigations. 

Given any non-negative integer n, its inventory is another integer consisting of a concatenation of integers c1 d1 c2 d2 ... ck dk , where each ci and di is an unsigned integer, every ci is positive, the di satisfy 0<=d1<d2<...<dk<=9, and, for each digit d that appears anywhere in n, d equals di for some i and d occurs exactly ci times in the decimal representation of n. For instance, to compute the inventory of 5553141 we set c1 = 2, d1 = 1, c2 = 1, d2 = 3, etc., giving 21131435. The number 1000000000000 has inventory 12011 ("twelve 0s, one 1"). 

An integer n is called self-inventorying if n equals its inventory. It is called self-inventorying after j steps (j>=1) if j is the smallest number such that the value of the j-th iterative application of the inventory function is self-inventorying. For instance, 21221314 is self-inventorying after 2 steps, since the inventory of 21221314 is 31321314, the inventory of 31321314 is 31123314, and 31123314 is self-inventorying. 

Finally, n enters an inventory loop of length k (k>=2) if k is the smallest number such that for some integer j (j>=0), the value of the j-th iterative application of the inventory function is the same as the value of the (j + k)-th iterative application. For instance, 314213241519 enters an inventory loop of length 2, since the inventory of 314213241519 is 412223241519 and the inventory of 412223241519 is 314213241519, the original number (we have j = 0 in this case). 

Write a program that will read a sequence of non-negative integers and, for each input value, state whether it is self-inventorying, self-inventorying after j steps, enters an inventory loop of length k, or has none of these properties after 15 iterative applications of the inventory function.

Input

A sequence of non-negative integers, each having at most 80 digits, followed by the terminating value -1. There are no extra leading zeros.

Output

For each non-negative input value n, output the appropriate choice from among the following messages (where n is the input value, j is a positive integer, and k is a positive integer greater than 1): 
n is self-inventorying 
n is self-inventorying after j steps 
n enters an inventory loop of length k 
n can not be classified after 15 iterations

Sample Input

22 
31123314 
314213241519 
21221314 
111222234459 
-1

Sample Output

22 is self-inventorying 
31123314 is self-inventorying 
314213241519 enters an inventory loop of length 2 
21221314 is self-inventorying after 2 steps 
111222234459 enters an inventory loop of length 2 

大概意思:

数字串都可以安装某种形式被压缩(压缩后元素按照从小到大排列,即d1<d2<...<dk):

c1 d1 c2 d2 .... ck dk 形式   //代表c个d(c>0 , 0<=d<=9)

有特别的数字串,其压缩前后的一模一样,定义这种数字串为self-inventorying

n为原数字串,

A为n压缩1次后的数字串,

B为n压缩2次后的数字串(即A压缩1次后的数字串)

....

K为n压缩k次后的数字串

 

数字串n的4种属性:

1、  n压缩1次就马上出现self-inventorying特性。压缩n次后即 n n n n n n n .....

2、  n压缩j次后的数字串J出现self-inventorying特性。压缩n次后即 n A B C....H I J J J J J J J

3、  n压缩j次后的数字串J,每再压缩K次,数字串J再次出现,即K次一循环。压缩n次后即n A B... J ..K J ..K J..K J

        其中K称为循环间隔,K>=2

4、  不满足以上条件

想法:

输入数字串长度不超过80,先去测试前3个属性,优先级依次降低,若都不满足,且如果循环大于15还是没有循环的现象产生则输出 n can not be classified after 15 iterations。压缩过程中,对于含有重复数字的个数是两位数(用整数计数,ck可能是两位数)的数字串,要把两位整数转化成字符串再进行存储。

 

代码实现:

#include<iostream>
#include<vector>
#include<string>
using namespace std;

void compres(string str, string &temp)	//temp作为返回参数
{
	int  count[10] = { 0 };//下标记录数字字符,内容记录数量
	for (int i = 0; i < str.length(); i++)
	{
		count[str.at(i) - '0']++;	//数字对应下标加1,表示这个数字字符数量加1
	}
	for (int i = 0; i < 10; i++)//下标正好从小到大
	{
		if (count[i] > 0)		//不等于0就说明压缩后存在这个字符
		{
			if (count[i]>9)		//处理个数为两位数的字符
			{
				temp += ((count[i] / 10) + '0');//十位
				temp += ((count[i] % 10) + '0');//个位
			}
			else
			{
				temp += (count[i] + '0');	//此数字字符数量
			}
			temp += (i + '0');	//数字字符   
		}
	}
}

int main()
{
	string n;	//初始输入的数字串
	vector<string> vectorN;
	while (cin >> n)
	{
		if (n[0] == '-')
			return 0;
		string temp = "";	//临时存储最新压缩过的数字串
		vectorN.push_back(n);
		int i = 0, k = -1;
		for (; i < 15; i++)
		{
			compres(vectorN.back(), temp);	//vector是动态增长的,传vector最后一个数字串作为参数
			if (temp == vectorN.back())	//这个数字串等于上一个,前两种情况
			{
				break;
			}
			for (int j = 0; j < vectorN.size(); j++)//隔几个一循环的情况
			{
				if (temp == vectorN.at(j))
				{
					k = i - j + 1;	//隔k次一循环
					break;
				}
			}
			if (k != -1)
				break;
			vectorN.push_back(temp);	//最后再附加上新压缩的数字串
			temp.clear();	//需要清空,不然每次都会在原有的基础上附加新数字串!!
		}
		if (i == 0)	//n n n n n n n ..... 的情况
		{
			cout << n << " is self-inventorying" << endl;
		}
		else if (i > 0 && i < 15)
		{
			if (k == -1)	//n A B C....H I J J J J J J J 的情况
				cout << n << " is self-inventorying after " << i << " steps" << endl;
			else            //n A B... J ..K J ..K J..K J
				cout << n << " enters an inventory loop of length " << k << endl;
		}
		else                //第四种情况
		{
			cout << n << " can not be classified after 15 iterations" << endl;
		}
		vectorN.clear();
	}

	return 0;
}

 

<vector>常用函数:

为了获得管理存储空间的能力,并且以一种有效的方式动态增长,vector占用了更多的存储空间
与其它动态序列容器相比(deques, lists and forward_lists), vector在访问元素的时候更加高效,
在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。


(1). 容量
向量大小: vec.size();    //一个数组就是1,两个数组就是2
向量最大容量: vec.max_size();
更改向量大小: vec.resize();
向量真实大小: vec.capacity();    //预分配的
向量判空: vec.empty();
减少向量大小到满足元素所占存储空间的大小: vec.shrink_to_fit(); //shrink_to_fit

(2). 修改
多个元素赋值: vec.assign(); //类似于初始化时用数组进行赋值
末尾添加元素: vec.push_back();
末尾删除元素: vec.pop_back();
任意位置插入元素: vec.insert();
任意位置删除元素: vec.erase();
交换两个向量的元素: vec.swap();
清空向量元素: vec.clear();

(3)迭代器
开始指针:vec.begin();
末尾指针:vec.end(); //指向最后一个元素的下一个位置
指向常量的开始指针: vec.cbegin(); //意思就是不能通过这个指针来修改所指的内容,
                                  但还是可以通过其他方式修改的,而且指针也是可以移动的。
指向常量的末尾指针: vec.cend();

(4)元素的访问
下标访问: vec[1]; //并不会检查是否越界
at方法访问: vec.at(1); //以上两者的区别就是at会检查是否越界,是则抛出out of range异常
访问第一个元素: vec.front();
访问最后一个元素: vec.back();
返回一个指针: int* p = vec.data(); //可行的原因在于vector在内存中就是一个连续存储的数组,
                                    所以可以返回一个指针指向这个数组。这是是C++11的特性。

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值