CF1214D Treasure Island
这题真的坑……
就这样,我看着机房里的其他同学一个一个在最后几分钟绝杀这道题,然后再看着他们一个一个FST……
首先,我们可以发现,答案肯定不会超过
所以,我们可以分类讨论三种答案:
1、
只要刚开始就走不到终点,答案就是
2、
如何判断只堵一个点就能使
我们把整个矩阵想象成一个图,
对于有向图呢?有向图必经点!
然而这是一个
然而,本题恶意卡
还有种解决方法是支配树,不过那个没多少人会……而且非常麻烦……
我们得充分挖掘本题的性质,发现有一个这样的性质:
..#.
.#..
#...
....
如果有一条这样的对角线上的每一个点都是'#',就无法到达终点。
于是,如果有一条对角线上只有一个'.',那么这个点就是必经点……吗?
我考场上就这么打了,就这么
考虑如下情况:
.#..
#...
..#.
.#..
那么
那么再用
我也这么打了,也
再考虑一个情况:
..#
.#.
.#.
那么
于是,我们再开一个数组
结论:如果存在一条对角线上只有一个'.',且这个点能从起点到达它再到达终点,那么它就是必经点。
3、
排除了其它情况,答案就是
注意事项:本题的范围是
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define res register int
#define ll long long
//#define cccgift
//#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
//char buf[1<<21],*p1=buf,*p2=buf;
namespace wode{
template<typename T>
inline void read(T &x)
{
static char ch;bool f=1;
for(x=0,ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') f=0;
for(;isdigit(ch);x=(x<<1)+(x<<3)+(ch^48),ch=getchar());x=f?x:-x;
}
template<typename T>
void print(T x)
{
if (x<0) putchar('-'),x=-x;
if (x>=10) print(x/10);
putchar(x%10+'0');
}
template<typename T>
inline void print(T x,char ap) {print(x);if (ap) putchar(ap);}
template<typename T>
inline T max(T x,T y) {return x<y?y:x;}
template<typename T>
inline T min(T x,T y) {return x<y?x:y;}
template<typename T>
inline void chkmax(T &x,T y) {x=x<y?y:x;}
template<typename T>
inline void chkmin(T &x,T y) {x=x<y?x:y;}
}
using wode::read;using wode::chkmin;using wode::chkmax;using wode::print;
int n,m,d[2000001];
bool f[1000001],g[1000001];
char s[1000001];
inline int getid(int x,int y) {
if(x<1||y<1||x>n||y>m) return 0;
return (x-1)*m+y;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(res i=1;i<=n;++i)
for(res j=1;j<=m;++j) cin>>s[getid(i,j)];
f[1]=true;
for(res i=1;i<=n;++i)
for(res j=1;j<=m;++j) if(s[getid(i,j)]=='.'&&(i>1||j>1)) f[getid(i,j)]|=f[getid(i-1,j)]|f[getid(i,j-1)];
if(!f[n*m]) return cout<<0<<endl,0;
g[n*m]=true;
for(res i=n;i;--i)
for(res j=m;j;--j) if(s[getid(i,j)]=='.'&&(i<n||j<m)) g[getid(i,j)]|=g[getid(i+1,j)]|g[getid(i,j+1)];
for(res i=1;i<=n;++i)
for(res j=1;j<=m;++j) if(f[getid(i,j)]&&g[getid(i,j)]) ++d[i+j]; //判断对角线
for(res i=3;i<n+m;++i) if(d[i]==1) return cout<<1<<endl,0; //注意起点和终点的那条对角线不能算!
cout<<2<<'\n';
cout<<flush;
return 0;
}