本题看似是一道简单的题,但由于输入的数据量过于庞大,最直接的解法是不能完成的。
该题的最主要思想是发现,只有每段数字的首位及其四周的8个数字有更变的可能,其他数字都与其左位已算出的数字相同。
这样就只用处理1000个数对*9个需要处理的格*9需要计算的数=81000。
如果算法不精依然容易超时。
方法:
1、计算出每个需计算的格子的位置、数值,存入数组中。
2、将数组按位置排序,再按要求从头遍历,计算结果并输出。
然而这样做,该题是有很多bug的,比如:
http://www.educity.cn/wenda/368388.html
详细论述了两种bug。
笔者鼓励你仔细解决这两种bug。
但告诉你一个偷懒的方法:
只要处理一下最后一行的第一个数字就可以了,或者说处理位于总长位置即超过数组大小1的位置的格子,这题poj就能过。
代码:
http://blog.csdn.net/lyy289065406/article/details/6648671
心得:
由于MAP内部采用红黑树结构,因此按理不应该速度很慢的。
但事实上如果插入次数很多,且不需要再插入过程中一直保持顺序,用数组记录再最后qsort要快一些。
qsort速度一直比自己写的快排程序快一点。
#include <iostream>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
int width;
int sum = 0;
map<int, int> MAP;
vector<pair<int, int> > ppvec;
int searchnum(int a) {
int k = 0, sum = 0;
while (sum <= a) {
sum += ppvec[k].second;k++;
}
return ppvec[k-1].first;
}
int zuidajueduizhi(int m) {
int x = m / width, y = m%width;
int zuida = -1;
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++) {
if (x + i >= 0 && x + i < sum / width&&y + j >= 0 && y + j < width) {
int k = (x + i)*width + y + j;
int kk = searchnum(k); int km = searchnum(m);
int kkk = abs(kk - km);
if (kkk > zuida)zuida = kkk;
}
}
return zuida;
}
void fieldplay() {
int sum_counter = 0; int x_counter, y_counter;
for (int i = 0; i <= ppvec.size(); i++) {
x_counter = sum_counter / width;
y_counter = sum_counter%width;
int tmp_counter;
for (int j = -1; j <= 1; j++) {
for (int l = -1; l <= 1; l++) {
tmp_counter = sum_counter + j*width + l;
if (x_counter + j >= 0 && tmp_counter<sum&&y_counter + l >= 0 && y_counter + l < width) {
//cout << tmp_counter << ' ' << searchnum(tmp_counter) << endl;
int m = (x_counter + j)*width + y_counter + l;
int k = zuidajueduizhi(m);
MAP.insert(make_pair(m, k));
}
}
}
/*if (y_counter > 1 && ppvec[i].second>width - y_counter + 2) { sum_counter = (x_counter + 1)*width; i--; }
else*/
if (i >= ppvec.size())break;
sum_counter += ppvec[i].second;
}
return;
}
void reset() {
MAP.clear();
ppvec.clear();
sum = 0;
return;
}
void print() {
cout << width << endl;
pair<int, int> pp = *MAP.begin();
for (map<int, int>::iterator ii=MAP.begin(); ii != MAP.end(); ii++) {
if (ii->second == pp.second)continue;
else {
int k = ii->first - pp.first;
cout << pp.second << ' ' << k << endl;
pp = *ii;
}
}
cout << pp.second << ' ' << sum - pp.first << endl;
cout << '0' << ' ' << '0' << endl;
return;
}
int main()
{
while (cin >> width) {
if (width == 0)break;
ppvec.clear();
int nnum, llen;
while (cin >> nnum >> llen) {
if (nnum == 0 && llen == 0)break;
ppvec.push_back(make_pair(nnum, llen));
sum += llen;
}
fieldplay();
print();
reset();
}
cout << '0' << endl;
return 0;
}