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]);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章