noip 1995 编码问题

题目描述
设有一个数组 A:ARRAY[0…N-1] OF INTEGER;数组中存放的元素为0~N-1之间的整数,且A[i]≠A[j](当i≠j时)。

例如:

   N=6时,有:A=(4,3,0,5,1,2)

   此时,数组A的编码定义如下:

   A[0]的编码为0;

   A[i]的编码为:在A[0],A[1],……A[i-1]中比A[i]的值小的个数(i=1,2……N-1)

∴上面数组A的编码为:B=(0,0,0,3,1,2)

程序要求解决以下问题:

① 给出数组A后,求出其编码;

② 给出数组A的编码后,求出A中的原数据。

输入格式
每个测试文件只包含一组测试数据,每组输入包含三行。

第一行输入整数N;

第二行输入有两种可能:

例如:

A=(4,3,0,5,1,2)

B=(0,0,0,3,1,2)

其中输入中的逗号和括号都是英文状态下的。

输出
当输入的是A=(…),则输出其编码。

当输入的是B=(…),则输出A中的原数据。

输出数据的格式和输入数据的格式是一样的。

样例输入
6
A=(4,3,0,5,1,2)
6
B=(0,0,0,3,1,2)

样例输出
B=(0,0,0,3,1,2)
A=(4,3,0,5,1,2)

只给出第二问解题思路了,这个问题还是比较有趣的。
我们学校的dalao教了我一个很好的方法,每一次都寻找数组最后一个0,因为前面的0都可能出现样例的情况,4 3 也会出现0 0,但最后一个0能保证目前它一定是最小的(贪心嘛,若后面有更小的,它必定不会为0),那就把当前能用的最小数塞进去,然后把该位置后面的所有数-1,再去重复前面的操作。这样做是因为这样就可以找到1在哪里,找到1也可以找到2,依次类推(其实很好懂,不懂手动模拟几下就懂了),这样非常好理解。

#include<cstdio>
#include<iostream>
using namespace std;
int n,a[10005],ans[10005];
bool vis[10005];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	for(int i=0;i<n;i++)
	{
		for(int j=n;j>=1;j--)
		{
			if(a[j]==0&&!vis[j])
			{
				vis[j]=true;
				ans[j]=i;
				for(int k=j;k<=n;k++)
				{
					a[k]--;
				}
				break;
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		printf("%d ",ans[i]);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_37073764/article/details/103467690