NOIP 助教的时候遇到了一个问题,题意是这样的:
这在规模比较小的时候是一道大水题,但是现在观察其规模:行和列的规模都有可能达到10万,从最坏情况来考虑,最坏时需要38,146.97265625G的内存,很显然,你家没这么大的内存…所以这题需要优化。如何优化,我们想到了指针。实际上,我们留意到这个矩阵是“巨大而稀疏的”,其实也就暗示我们:那些没内容的内存单元根本不用去定义,而每一列的数据缩紧之后“扎堆”放在一起就好了(万事俱备,只欠输出),那么不妨定义列指针数组即可。这里占用内存最显著的应该是储存的数据了,最坏时也只需要0.3814697265625G的内存,规模一下子降了下来。
解题步骤:
1.首先,定义列指针数组(以往熟悉的是行指针数组,这里稍作转变)、每个内存位置所对应数值的映射数组、记录每一列有多少个数据的数组(便于后续为每一列动态分配空间)
2.完成K次读入操作,读入x(这个变量随意,炮灰,后续不会用到,只是输入时有用(占位))、读入y记录在y数组里、对应列的计数器自增
3.for循环为每一列动态分配空间
4.逐项输出
代码:
#include<iostream>
using namespace std;
#define MAX 100001
int main()
{
int n,m,k;
cin>>n>>m>>k;
int* row[MAX];
int x; //x随便开一个变量就好
int y[MAX];
int c[MAX];
int store[MAX]={0};
for(int i=1;i<=k;i++)
{
cin>>x>>y[i]>>c[i]; //这里需要用数组来记录哪一列和对应数值
store[ y[i] ]++; //计数器对应++
}
for(int i=1;i<=m;i++)
row[i]=new int[ store[i] ]; //动态分配列空间
for(int i=1;i<=k;i++)
{
*row[ y[i] ]=c[i]; //采用解引用运算符,写入数据
row[ y[i] ]++; //写完之后那一列的指针要对应“下移”
}
for(int i=1;i<=m;i++)
for(int j=store[i];j>0;j--)
cout<<*(row[i]-j)<<" "; //由于每一列对应的头指针位置已经是偏移的了,所以需要再用一个二重循环来顺序输出
return 0;
}
upd: 今天整理博客,发现这里可以还有可以添加方法,参见数据结构中《数组和广义表》