Problem
Geologists sometimes divide an area of land into different regions based on where rainfall flows down to. These regions are called drainage basins.
Given an elevation map (a 2-dimensional array of altitudes), label the map such that locations in the same drainage basin have the same label, subject to the following rules.
- From each cell, water flows down to at most one of its 4 neighboring cells.
- For each cell, if none of its 4 neighboring cells has a lower altitude than the current cell's, then the water does not flow, and the current cell is called a sink.
- Otherwise, water flows from the current cell to the neighbor with the lowest altitude.
- In case of a tie, water will choose the first direction with the lowest altitude from this list: North, West, East, South.
Every cell that drains directly or indirectly to the same sink is part of the same drainage basin. Each basin is labeled by a unique lower-case letter, in such a way that, when the rows of the map are concatenated from top to bottom, the resulting string is lexicographically smallest. (In particular, the basin of the most North-Western cell is always labeled 'a'.)
Input
The first line of the input file will contain the number of maps, T. T maps will follow, each starting with two integers on a line -- H and W -- the height and width of the map, in cells. The next H lines will each contain a row of the map, from north to south, each containing W integers, from west to east, specifying the altitudes of the cells.
Output
For each test case, output 1+H lines. The first line must be of the form
Case #X:
where X is the test case number, starting from 1. The next H lines must list the basin labels for each of the cells, in the same order as they appear in the input.
Limits
T ≤ 100;
Small dataset
1 ≤ H, W ≤ 10;
0 ≤ altitudes < 10.
There will be at most two basins.
Large dataset
1 ≤ H, W ≤ 100;
0 ≤ altitudes < 10,000.
There will be at most 26 basins.
这个题目其实是连通块标记问题, 如果水能从P0(x0,y0)流到p1(x1, y1),就说明p0和p1是连通的.
然后把所有的连通块标记出来, 最后按照从左到右,从上到下的顺序重新填写连通块的标记号码.
这个题目我是用类似于并查集的方法来标记连通块的, 最后再对块进行排序.
由于一开始没有排序,所以递交失败了,后来加上排序后,small set成功了,但是最后,成绩出来的时候, big set的结果不对,到现在还没找到问题.....
上代码(big set有问题):
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
int SetVal(char* pVal, int* pPar, int nPos)
{
if(pVal[nPos]==0)
{
pVal[nPos] = SetVal(pVal, pPar, pPar[nPos]);
}
return pVal[nPos];
}
int main()
{
FILE* fp;
int i, x, y;
fp = fopen("1.txt", "r");
int nRound = 0;
fscanf(fp, "%d", &nRound);
for(i=0; i<nRound; i++)
{
int nWidth, nHeight;
fscanf(fp, "%d %d", &nHeight, &nWidth);
int* pHei = (int*)malloc(nWidth*nHeight*sizeof(int));
int* pPar = (int*)malloc(nWidth*nHeight*sizeof(int));
char* pVal = (char*)malloc(nWidth*nHeight*sizeof(char));
memset(pVal, 0, nWidth*nHeight*sizeof(char));
int* pHeiT = pHei;
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++, pHeiT++)
{
fscanf(fp, "%d", pHeiT);
}
}
int nPos = 0;
int nChar = 0;
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++, nPos++)
{
int nHei = pHei[nPos];
int nMinHei = 0xFFFFFF;
int nMinPos;
if(y>0)
{
if(pHei[nPos-nWidth]<nMinHei)
{
nMinHei = pHei[nPos-nWidth];
nMinPos = nPos-nWidth;
}
}
if(x>0)
{
if(pHei[nPos-1]<nMinHei)
{
nMinHei = pHei[nPos-1];
nMinPos = nPos-1;
}
}
if(x<nWidth-1)
{
if(pHei[nPos+1]<nMinHei)
{
nMinHei = pHei[nPos+1];
nMinPos = nPos+1;
}
}
if(y<nHeight-1)
{
if(pHei[nPos+nWidth]<nMinHei)
{
nMinHei = pHei[nPos+nWidth];
nMinPos = nPos+nWidth;
}
}
if(nMinHei<nHei)
{
pPar[nPos] = nMinPos;
}
else
{
pPar[nPos] = nPos;
pVal[nPos] = 'a'+nChar;
nChar++;
}
}
}
nPos = 0;
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++, nPos++)
{
SetVal(pVal, pPar, nPos);
}
}
char* pMask = (char*)malloc(nChar*sizeof(char));
int* pMinPos = (int*)malloc(nChar*sizeof(int));
for(x=0; x<nChar; x++)
{
pMask[x] = x;
pMinPos[x] = 0xFFFFFF;
}
nPos = 0;
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++, nPos++)
{
if(nPos<pMinPos[pVal[nPos]-'a'])
{
pMinPos[pVal[nPos]-'a'] = nPos;
}
}
}
for(y=0; y<nChar; y++)
{
for(x=0; x<nChar; x++)
{
if(pMinPos[y]<pMinPos[x])
{
int nTmp;
nTmp = pMinPos[y];
pMinPos[y] = pMinPos[x];
pMinPos[x] = nTmp;
nTmp = pMask[y];
pMask[y] = pMask[x];
pMask[x] = nTmp;
}
}
}
printf("Case #%d:/n", i+1);
nPos = 0;
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++, nPos++)
{
printf("%c ", pMask[pVal[nPos]-'a']+'a');
}
printf("/n");
}
free(pMask);
free(pHei);
free(pPar);
free(pVal);
}
fclose(fp);
return 0;
}