POJ1016-Numbers That Count

Numbers That Count
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 21528   Accepted: 7227

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.

链接

一、题意

        给定一个数字串n,对其进行统计每个数字出现了几次,记为di出现了ci次,然后对于其中所有ci不等于零的di,我们将其排列为新的数字串。如11223344,其中1,2,3,4各出现了两次,其余数字出现0次,则重新排列后为c1d1c2d2c3d3c4d4,将对应的值带入就是21222324。现在判断给定的数字串是否满足下列要求:

  1. 该数字串是自循环的。即n经过一次操作后还是n。
  2. 该数字串经过j次操作后进入自循环。
  3. 该数字串能够进入长度为k的循环。注意与自循环的区别,自循环为n->n,长度为0。
  4. 该数字串不满足这些条件。

二、思路

        要注意的是,这些判断是有优先级的,在操作15次之前,即使出现循环也不能退出循环。知道这一点后题目应该就比较简。可以用map或vector存储中间产生的所有序列,在每次产生新序列时先判断是否是自循环,再判断是否有出现循环。

三、代码

#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <numeric>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <utility>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>

using namespace std;
typedef long long ll;
const int MAXN = 100;
const int MOD7 = 1000000007;
const int MOD9 = 1000000009;
const int INF = 2000000000;//0x7fffffff
const double EPS = 1e-9;
const double PI = 3.14159265358979;
const int dir_4r[] = { -1, 1, 0, 0 };
const int dir_4c[] = { 0, 0, -1, 1 };
const int dir_8r[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int dir_8c[] = { -1, 0, 1, -1, 1, -1, 0, 1 };

int cnt[MAXN];
char digits[MAXN];
char buf1[MAXN];
char buf2[MAXN];
bool loop;//判断是否出现环
int loopsize;
map<string, int> mp;

void fun(char *str, int &index, int cnt) {
	if (cnt == 0)
		return;
	int d = cnt % 10;
	cnt /= 10;
	fun(str, index, cnt);
	str[index++] = d + '0';
}

void inventory(char *in, char *out) {
	memset(cnt, 0, sizeof(cnt));
	for (int i = 0; in[i]; ++i)
		cnt[in[i] - '0']++;

	int index = 0;
	for (int i = 0; i < 10; ++i) {
		if (cnt[i]) {
			fun(out, index, cnt[i]);
			out[index++] = i + '0';
		}
	}
	out[index++] = '\0';
}

bool isSelfInventory(char *buf1, char *buf2) {
	inventory(buf1, buf2);
	if (strcmp(buf1, buf2) == 0)
		return true;
	else
		return false;
}

int solve() {
	int index = 0;
	map<string, int>::iterator it;
	mp.clear();

	loop = false;
	loopsize = INF;
	strcpy(buf1, digits);
	while (index <= 15) {
		if (isSelfInventory(buf1, buf2))
			break;
		it = mp.find(string(buf1));
		if (it != mp.end()) {
			loop = true;
			loopsize = min(loopsize, index - it->second);
		}

		mp[string(buf1)] = index++;
		strcpy(buf1, buf2);
	}
	return index;
}

int main() {
	while (scanf("%s", digits)) {
		if (digits[0] == '-')
			break;

		int ans = solve();
		if (ans == 0)
			printf("%s is self-inventorying\n", digits);
		else if (ans <= 15)
			printf("%s is self-inventorying after %d steps\n", digits, ans);
		else if (loop)
			printf("%s enters an inventory loop of length %d\n", digits, loopsize);
		else
			printf("%s can not be classified after 15 iterations\n", digits);
	}

	//system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/baoqiaoben/article/details/80085965