火星探险问题
Description
火星探险队的登陆舱将在火星表面着陆,登陆舱内有多部障碍物探测车。
登陆舱着陆后,探测车将离开登陆舱向先期到达的传送器方向移动。
探测车在移动中还必须采集岩石标本。
每一块岩石标本由最先遇到它的探测车完成采集。
每块岩石标本只能被采集一次。
岩石标本被采集后,其他探测车可以从原来岩石标本所在处通过。
探测车不能通过有障碍的地面。
本题限定探测车只能从登陆处沿着向南或向东的方向朝传送器移动,而且多个探测车可以在同一时间占据同一位置。
如果某个探测车在到达传送器以前不能继续前进,则该车所采集的岩石标本将全部损失。
用一个PXQ 网格表示登陆舱与传送器之间的位置。登陆舱的位置在(
X1,Y1
)处,传送器的位置在(
XP,YQ
)处。
给定每个位置的状态,计算探测车的最优移动方案,使到达传送器的探测车的数量最多,而且探测车采集到的岩石标本的数量最多。
Input
第
1
行为探测车数,第
接下来的
用
3
个数字表示火星表面位置的状态:
Output
程序运行结束时,将能探索到的岩石标本数目输出。
Sample Input
2
10
8
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0
0 0 0 1 0 2 0 0 0 0
1 1 0 1 2 0 0 0 0 1
0 1 0 0 2 0 1 1 0 0
0 1 0 1 0 0 1 1 0 0
0 1 2 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0
Sample Output
2
Solution
我们把每个格子与他能够到达的格子连一条边。
如果此格子有岩石标本,那么就再加一个点,再连一条容量为
1
<script type="math/tex" id="MathJax-Element-13">1</script> 的边到这个点,然后从这个点连一条边回到这个格子。
跑一遍最大费用流就行了。
Code
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <queue>
- #define ss 0
- #define tt 100000
- #define INF 0x3f3f3f3f
- #define Min(x,y) ((x)<(y)?(x):(y))
- #define PLA(x,y) ((x)*qs+(y))
- #define ANOTHER 1000
- using namespace std;
- int n,cnt,ans,ps,qs;
- int nxt[100010],head[100010],data[100010];
- int flow[100010],wei[100010];
- int dis[100010];
- int pre[100010];
- int maps[100][100];
- bool vis[100][100];
- queue<int>q;
- bool in_stack[100010];
- void add(int x,int y,int a,int b){
- nxt[cnt]=head[x];data[cnt]=y;wei[cnt]=b;flow[cnt]=a;head[x]=cnt++;
- nxt[cnt]=head[y];data[cnt]=x;wei[cnt]=-b;flow[cnt]=0;head[y]=cnt++;
- }
- bool BFS(){
- memset(dis,0x3f,sizeof dis);dis[ss]=0;in_stack[ss]=true;q.push(ss);pre[ss]=pre[tt]=-1;
- while(!q.empty()){
- int now=q.front();
- q.pop();
- in_stack[now]=false;
- for(int i=head[now];i!=-1;i=nxt[i]){
- if(flow[i]!=0&&dis[data[i]]>dis[now]+wei[i]){
- dis[data[i]]=dis[now]+wei[i];
- pre[data[i]]=i^1;
- if(!in_stack[data[i]]){
- in_stack[data[i]]=true;
- q.push(data[i]);
- }
- }
- }
- }
- return pre[tt]!=-1;
- }
- void dfs(){
- int Low=INF;
- for(int i=pre[tt];i!=-1;i=pre[data[i]])Low=Min(Low,flow[i^1]);
- for(int i=pre[tt];i!=-1;i=pre[data[i]])flow[i^1]-=Low,flow[i]+=Low;
- ans+=Low*dis[tt];
- }
- void Dfs(int p1,int p2){
- vis[p1][p2]=true;
- if(p1+1<=ps&&maps[p1+1][p2]!=1){
- if(!maps[p1+1][p2])add(PLA(p1,p2),PLA(p1+1,p2),n,0);
- if(maps[p1+1][p2]==2){
- add(PLA(p1,p2),PLA(p1+1,p2),n,0);
- add(PLA(p1,p2),PLA(p1+1,p2)+ANOTHER,1,0);
- }
- else add(PLA(p1,p2),PLA(p1+1,p2),n,0);
- if(!vis[p1+1][p2])Dfs(p1+1,p2);
- }
- if(p2+1<=qs&&maps[p1][p2+1]!=1){
- if(!maps[p1][p2+1])add(PLA(p1,p2),PLA(p1,p2+1),n,0);
- if(maps[p1][p2+1]==2){
- add(PLA(p1,p2),PLA(p1,p2+1),n,0);
- add(PLA(p1,p2),PLA(p1,p2+1)+ANOTHER,1,0);
- }
- else add(PLA(p1,p2),PLA(p1,p2+1),n,0);
- if(!vis[p1][p2+1])Dfs(p1,p2+1);
- }
- }
- int main(){
- memset(head,-1,sizeof head);
- scanf(”%d%d%d”,&n,&qs,&ps);
- for(int i=1;i<=ps;i++)
- for(int j=1;j<=qs;j++){
- scanf(”%d”,&maps[i][j]);
- add(PLA(i,j)+ANOTHER,PLA(i,j),1,-1);
- }
- Dfs(1,1);
- add(ss,PLA(1,1),n,0);
- add(PLA(ps,qs),tt,n,0);
- while(BFS())dfs();
- if(maps[ps][qs]==2)ans++;
- if(maps[1][1]==2)ans++;
- printf(”%d\n”,-ans);
- return 0;
- }