NOI’95 “同创杯”全国青少年信息学(计算机)奥林匹克竞赛
分区联赛复赛测试数据(初中组)
第四题
问题:
编码问题:设有一个数组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中的原数据。
输出:
①由数组求编码:共15分(5%+5%+5%)
a 输入:N=6 A=(0,1,2,3,4,5)
输出: B=(0,1,2,3,4,5)
b 输入:N=6 A=(5,4,3,2,1,0)
输出: B=(0,0,0,0,0,0)
c 输入:N=8 A=(1,0,3,2,5,4,7,6)
输出: B=(0,0,2,2,4,4,6,6)
②由编码求原数组:共15分(5%+5%+5%)
a 输入:N=5 B=(0,0,0,0,0)
输出: A=(4,3,2,1,0)
b 输入:N=10 B=(0,1,2,3,4,5,6,7,8,9)
输出: A=(0,1,2,3,4,5,6,7,8,9)
c 输入:N=7 B=(0,0,0,0,4,5,6)
输出: A=(3,2,1,0,4,5,6)
解析
本题的是编码类型的题,难点在加解密的算法设计上。
首先要搞清楚加解密的原理,然后在进行程序上的设计。
相对而言,这道题加密的理解比较容易,解密是逆向推导,相对复杂了些。
具体代码:
#include <QCoreApplication>
#include<iostream>
#include<time.h>
using namespace std;
#define MAXN 100
int srcArray[MAXN]; //原文数组
int codeArray[MAXN]; //加密后产生的数组
int decodeArray[MAXN]; //解密后的数组
enum {CODEMODE = 0, DECODEMODE =1};
void GetRandom(int * random,int size);
void GetCode(int *arrayA,int *arrayB,int size);
void GetDecode(int *arrayA,int *arrayB,int size);
void printArray(int *parray,int size,int mode);
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
cout<<"Hello NOIP!"<<endl;
cout<<"Enter the size of array:"<<endl;
int size = 0;
cin >>size;
cout<< "The size of array is:"<<size<<endl;
GetRandom(srcArray,size); // 产生随机数列
GetCode(srcArray,codeArray,size); //加密
printArray(codeArray,size,CODEMODE); //打印密文
GetDecode(codeArray,decodeArray,size); //解密
printArray(decodeArray,size,DECODEMODE); //打印解密后的原文
return a.exec();
}
// 随机产生个数为size的不同的数
void GetRandom(int *random,int size)
{
int i, j[size], k;
for (i = 0; i < size; i++)
{
j[i] = i;
}
for(i = 0; i < size; i++)
{
//生成第i个随机数
srand((unsigned)time(NULL));
k = (int)rand() % size;//k为下标
//cout<<k<<" ";
while (j[k] == -1)
{
k = (k + 1) % size;
}
random[i] = j[k];
cout<< random[i]<< " ";
j[k] = -1;
}
cout<<endl;
}
//加密算法
void GetCode(int *arrayA,int *arrayB,int size)
{
arrayB[0]=0;
int cnt = 0;
for(int i = 1;i<size;i++)
{
for(int j = 0;j<i;j++)
{
if(arrayA[j]<arrayA[i])
{
cnt++;
arrayB[i] = cnt;
}
}
cnt = 0;
// cout<< "The coded is:"<<arrayB[i]<<" ";
}
}
//解密算法
void GetDecode(int *arrayA,int *arrayB,int size)
{
int conf[size]; //参考数组
for (int i = 0; i < size; i++)
{
conf[i] = i;
}
arrayB[size-1] = arrayA[size-1]; //确定最后一位数
int temp = arrayB[size-1];
conf[temp] = -1;
int cnt = 0;
for(int i = size-2;i>=0;i--)
{
for(int j = 0 ;j<size;j++)
{
if(conf[j]>=0)
{
cnt++;
if(cnt == arrayA[i]+1)
{
cnt = j;
break;
}
}
}
arrayB[i] = conf[cnt];
conf[cnt] =-1;
cnt = 0;
}
}
void printArray(int *parray,int size,int mode)
{
if(mode == CODEMODE )
{
cout<< "The coded is:"<<endl;
}
else
{
cout<< "The decoded is:"<<endl;
}
for(int i=0;i<size;i++ )
{
cout<<parray[i]<<" ";
}
cout<<endl;
}
程序编译后输出: