您的位置:首页 > 大数据 > 人工智能

Problem B. Rain Google APAC 2017 University Test Round A

2017-02-05 21:30 405 查看
这一题最初算法错了,竟然过了小数据,然后大数据一直WA,debug了好几天T_T。

最开始的想法是把非边界的点按照高度排序。从高度最低的点开始BFS。如果当前点所在的平面(同样高度的,包含当前点的连通平面)可以积水,就把该平面的高度更改为积水高度(积水区域border的最低高度)。

然而我更改过高度就没去管那些点了=。=实际上,被更改高度的点可能还没有被BFS,可是那些点和其他点高度大小关系已经变了。所以按照之前的次序BFS就不是先考虑高度最低的点了。e.g., 五个相邻的点原先为5 3 2 1 5,更改后为5 3 2 4 5,如果BFS还是从倒数第二个的点开始,那么因为2<4,就会认为无法积水。积水过程是5 3 3 4 5 -> 5 4 4 4 5。实际上如果先从2 BFS,仍然可以积水。积水过程是5 3 3 4 5 ->
5 4 4 4 5 -> 5 5 5 5 5。

正解是维护一个优先队列,这样每次BFS一个点之后都会将所有点按照更改后的高度高度重新排序。另外从优先队列pop元素之后,如果是更改之前的值,直接ignore。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<ctype.h>
#include<map>
#include<time.h>
#include<set>
#include<bitset>
#include<sstream>
using namespace std;
//Google APAC2017 Round A Problem B. Rain

const int maxn=60;
int T;
int R;
int C;
int dx[]={0,-1,0,1};
int dy[]={-1,0,1,0};
int mp[maxn][maxn];
bool vis[maxn][maxn];
int ans;
class node
{
public:
int x;
int y;
int height;
public:
node()
{
x=0;
y=0;
height=0;
}
node(int x0,int y0,int h)
{
x=x0;
y=y0;
height=h;
}
bool operator < (node b) const
{
if(height==b.height)
{
if(x==b.x)
{
return y>b.y;
}
return x>b.x;
}
return height>b.height;
}
bool operator > (node b) const
{
if(height==b.height)
{
if(x==b.x)
{
return y<b.y;
}
return x<b.x;
}
return height<b.height;
}
};
set<node>mark;
priority_queue<node>prique;
int BFS(pair<int,int>st)
{
int minborder=0x3f3f3f3f;
int area=0;
memset(vis,false,sizeof(vis));
vector<pair<int,int> >neigh;
neigh.clear();
queue<pair<int,int> >que;
while(!que.empty()) que.pop();
que.push(st);
while(!que.empty())
{
pair<int,int>now=que.front();
neigh.push_back(now);
que.pop();
vis[now.first][now.second]=true;
if(now.first==1||now.first==R||now.second==1||now.second==C)//at the border
{
return 0;
}
area++;
for(int i=0;i<4;i++)
{
int nextx=now.first+dx[i];
int nexty=now.second+dy[i];
if(nextx<1||nextx>R||nexty<1||nexty>C) continue;
if(vis[nextx][nexty]==true) continue;
if(mp[nextx][nexty]>mp[st.first][st.second])
{
//                cout<<mp[nextx][nexty]<<endl;
minborder=min(minborder,mp[nextx][nexty]);
continue;
}
else if(mp[nextx][nexty]<mp[now.first][now.second])
{
return 0;
}
else if(mp[nextx][nexty]==mp[now.first][now.second])
{
que.push(make_pair(nextx,nexty));
vis[nextx][nexty]=true;
}
//if smaller?
//calc sum(heigh gap) instead of using product once
}
}
//   cout<<"here "<<st.first<<" "<<st.second<<" "<<area<<" "<<minborder<<" "<<mp[st.first][st.second]<<endl;
if(minborder==0x3f3f3f3f) return 0;
int ret=0;
for(int i=0;i<neigh.size();i++)
{
//        cout<<neigh[i].first<<" "<<neigh[i].second<<" "<<mp[neigh[i].first][neigh[i].second]<<" "<<st.first<<" "<<st.second<<" "<<mp[st.first][st.second]<<endl;
mark.insert(node(neigh[i].first,neigh[i].second,mp[neigh[i].first][neigh[i].second]));
ret+=minborder-mp[neigh[i].first][neigh[i].second];
mp[neigh[i].first][neigh[i].second]=minborder;
prique.push(node(neigh[i].first,neigh[i].second,mp[neigh[i].first][neigh[i].second]));//neigh's height must < minborder
}
//    cout<<"ret: "<<ret<<endl;
return ret;//update value of mp?
}
int tmpmp[maxn][maxn];
int main()
{
freopen("B-small-practice.in","r",stdin);
freopen("B-small-practice.out","w",stdout);
scanf("%d",&T);
for(int ca=1;ca<=T;ca++)
{
scanf("%d %d",&R,&C);
memset(mp,0,sizeof(mp));
memset(tmpmp,0,sizeof(tmpmp));
while(!prique.empty()) prique.pop();
mark.clear();
ans=0;
for(int i=1;i<=R;i++)
{
for(int j=1;j<=C;j++)
{
scanf("%d",&mp[i][j]);
tmpmp[i][j]=mp[i][j];
if(i==1||j==1||i==R||j==C) continue;
prique.push(node(i,j,mp[i][j]));
}
}
while(!prique.empty())
{
node tmp=prique.top();
prique.pop();
//            cout<<tmp.x<<" "<<tmp.y<<" "<<tmp.height<<" "<<mark.count(tmp)<<endl;
//            continue;
if(mark.count(tmp)==0)
{

ans+=BFS(make_pair(tmp.x,tmp.y));
}
}
printf("Case #%d: %d\n",ca,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: