//7983483    vrs    2227    Accepted    1120K    235MS    C++    2852B    2010-12-08 20:02:00
//POJ 2227 凹凸坑装水 优先队列(堆)+floodfill(bfs)
//黑书中的一道题 先分析边界点,弄为障碍物,把他们放到堆里,然后从最小的开始,进行一次floodfill(木桶原理)
//一直循环直到堆为空,每次floodfill是使用队列做一次广搜
#include<stdio.h>
#include<queue>
using namespace std;
#define bool int
#define MAXNUM 90005

 

typedef struct _BLOCK
{
    long key;
    int row;
    int col;
}BLOCK;
BLOCK block[MAXNUM];
long n;

long map[305][305];
bool mapState[305][305];
int director[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
unsigned long long sumJuice;
queue <BLOCK> *qu;

void swap(long i,long j)
{
    BLOCK temp;
    //这里尝试了用memcpy,感觉不错
    memcpy(&temp,&block[i],sizeof(BLOCK));
    memcpy(&block[i],&block[j],sizeof(BLOCK));
    memcpy(&block[j],&temp,sizeof(BLOCK));
    /*
    temp.key=block[i].key;
        temp.col=block[i].col;
        temp.row=block[i].row;
   
        block[i].key=block[j].key;
        block[i].row=block[j].row;
        block[i].col=block[j].col;
   
        block[j].key=temp.key;
        block[j].row=temp.row;
        block[j].col=temp.col;*/
}

void Insert(long data,int row,int col)
{
    long father,son;
    n++;
    block[n].key=data;
    block[n].row=row;
    block[n].col=col;
    son=n;
    while(son>1)
    {
        father=son/2;
        if(block[father].key>block[son].key)
            swap(father,son);
        else
            break;
        son=father;
    }
}

long Top()
{
    return 1;
}

bool IsEmpty()
{
    if(n==0)
        return 1;
    else
        return 0;
}

void Pop()
{
    long father,son;
    swap(1,n);
    n--;
    father=1;
    while(father<=n/2)
    {
        son=father*2;
        if(son+1<=n && block[son].key>block[son+1].key)
            son++;
        if(block[father].key>block[son].key)
            swap(father,son);
        else
            break;
        father=son;
    }
}

//就是一个bfs
void FloodFill(int rowNum,int colNum)
{
    int i,row,col;
    BLOCK curBlock,tempBlock;
    while(!qu->empty())
    {
        curBlock=qu->front();
        qu->pop();
        for(i=0;i<4;i++)
        {
            row=curBlock.row+director[i][0];
            col=curBlock.col+director[i][1];
            if(row>0 && row<rowNum-1 && col>0 && col<colNum-1 && !mapState[row][col])
            {
                mapState[row][col]=1;
                if(curBlock.key<map[row][col])
                    Insert(map[row][col],row,col);
                else
                {
                    if(curBlock.key-map[row][col]>0)
                        sumJuice+=(unsigned long long)(curBlock.key-map[row][col]);
                    tempBlock.key=curBlock.key;
                    tempBlock.row=row;
                    tempBlock.col=col;
                    qu->push(tempBlock);
                }
            }
        }
    }
}

void Init(int col,int row)
{
    int i,j;
    memset(mapState,0,sizeof(mapState));
    n=0;
    sumJuice=0;
    qu=new queue<BLOCK>;
    for(j=1;j<col-1;j++)
    {
        Insert(map[0][j],0,j);
        mapState[0][j]=1;
        Insert(map[row-1][j],row-1,j);
        mapState[row-1][j]=1;
    }
    for(i=1;i<row-1;i++)
    {
        Insert(map[i][0],i,0);
        mapState[i][0]=1;
        Insert(map[i][col-1],i,col-1);
        mapState[i][col-1]=1;
    }
    mapState[0][0]=1;
    mapState[0][col-1]=1;
    mapState[row-1][0]=1;
    mapState[row-1][col-1]=1;
}

int main()
{
    int colNum,rowNum;
    int i,j;
    int curPos;
    scanf("%d%d",&colNum,&rowNum);
    for(i=0;i<rowNum;i++)
        for(j=0;j<colNum;j++)
            scanf("%ld",&map[i][j]);
    Init(colNum,rowNum);
    while(!IsEmpty())
    {
        curPos=Top();
        qu->push(block[curPos]);
        FloodFill(rowNum,colNum);
        Pop();
    }
    printf("%lld\n",sumJuice);
    delete qu;
    return 0;
}

/*一个测试数据
13 6
5 8 7 7 1 2 4 3 2 4 6 8 9
5 2 1 5 1 5 7 1 2 6 5 4 8
7 5 5 1 4 8 6 5 2 1 8 9 2
8 9 6 9 1 5 2 5 8 6 2 1 4
9 8 9 9 4 8 5 2 4 8 9 6 2
1 5 2 5 2 6 8 5 4 7 8 2 3
answer=28

posted on 2010-12-08 20:50  VRS  阅读(510)  评论(0编辑  收藏  举报