题目链接 题目大意 一个n*m的矩阵,Vasya想要从矩阵矩阵的(1,1)(左上角)走到(n,m)(右下角),矩阵中有一些格不能走,一次只能向下或向右。现在你可以使一些格变得不能走来阻止他
题目链接
题目大意
一个n*m的矩阵,Vasya想要从矩阵矩阵的(1,1)(左上角)走到(n,m)(右下角),矩阵中有一些格不能走,一次只能向下或向右。现在你可以使一些格变得不能走来阻止他走到,问最少改变几个格。 (3<=n*m<=1000000)
思路
直接把起点或终点围住不就好了吗。这是我第一发WA,然后发现我好傻呀,矩阵中本来就有一些障碍。
把矩阵按行加列分层,即,
则从左上角到右下角的路径一定经过每一层的至少一个格,那么我从起点bfs一遍统计出每层能到达的格分别有多少个,我只需要把其中一层能到达的全部格都变成障碍就好,那一层需要变得少就变哪一层。于是我又WA了一发。
上述想法还有一个漏洞,就是有可能这一层的这个格是可以到达的,但是从它又到不了(n,m)(例如,下图的样例),这一层就完全可以不用把这个格变为障碍,但是统计能到达格的时候又记录了它。出现这样的情况只能因为走到有些格就在已无法到达终点了,那么这些点无异于障碍,因此加一个预处理把这样的点都变成障碍就好(注意要从终点向前找)。
代码
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 int n,m; 6 char s[1000006]; 7 int cnt[1000006],dis[1000006]; 8 queue<int> q; 9 10 int main() 11 { 12 scanf("%d%d",&n,&m); 13 char ch=getchar(); 14 for(int i=1;i<=n;i++) 15 { 16 while(ch!=‘.‘&&ch!=‘#‘)ch=getchar(); 17 for(int j=1;j<=m;j++) 18 { 19 s[(i-1)*m+j]=ch; 20 ch=getchar(); 21 } 22 } 23 for(int i=m*n-1;i>1;i--)//预处理 24 { 25 int r=(i+m-1)/m,c=i%m; 26 if(c==0)c=m; 27 if(c+1>m||(c+1<=m&&s[(r-1)*m+c+1]==‘#‘)) 28 if(r+1>n||(r+1<=n&&s[r*m+c]==‘#‘))s[i]=‘#‘; 29 } 30 q.push(1); 31 dis[1]=2; 32 while(!q.empty())//bfs 33 { 34 int dang=q.front();q.pop();cnt[dis[dang]]++; 35 int r=(dang+m-1)/m,c=dang%m; 36 if(c==0)c=m; 37 if(c+1<=m&&s[(r-1)*m+c+1]==‘.‘&&dis[(r-1)*m+c+1]==0) 38 { 39 dis[(r-1)*m+c+1]=dis[dang]+1; 40 q.push((r-1)*m+c+1); 41 } 42 if(r+1<=n&&s[r*m+c]==‘.‘&&dis[r*m+c]==0) 43 { 44 dis[r*m+c]=dis[dang]+1; 45 q.push(r*m+c); 46 } 47 } 48 int ans=2; 49 for(int i=3;i<n+m;i++) 50 { 51 ans=min(ans,cnt[i]); 52 } 53 cout<<ans<<endl; 54 return 0; 55 }