cf 106d Treasure Island


点击打开链接


题意: 

给你一个地图,地图上 ‘.‘表示能走的点。’#' 表示不能走的点,

然后给你最多26个出发点,然后给你走的方法, 如果按照给的方法,完全可行(不超界,不遇见'#'),就是可行点,

最后把所有可行点按升序输出,没有输出no。


题解:  

我算了一下复杂度,感觉大暴力可能过,于是一个一个位移,跑了快60个测试点,,,,TLE。

就在纠结怎么优化,后来一次走一行或一列,就不会超时了,这样的话,要记录每一行和每一列#数量 的前缀和,

如果能走,前缀和之差一定是0.


#include<bits/stdc++.h>

using namespace std;
const int maxn=1010;
const int maxk=1e5+100;
const int inf=0xfffffff;
int n,m,k,cnt=0;
char ma[maxn][maxn];
int ps[maxn][maxn],pr[maxn][maxn];
int ans[30];
struct node{
    char d;
    int s;
}a[maxk];
int main(){
    memset(ma,'#',sizeof(ma));
    cin>>n>>m;
    for(int i=1;i<=n;++i) {
        scanf("%s",ma[i]+1),ma[i][m+1]='#';
        for(int j=1;j<=m;++j){
            ps[i][j]=ps[i][j-1];
            pr[i][j]=pr[i-1][j];
            if(ma[i][j]=='#') ps[i][j]++,pr[i][j]++;
        }
    }
    cin>>k;
    for(int i=1;i<=k;++i) {getchar();
            scanf("%c %d",&a[i].d,&a[i].s);
    }
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j){
            if(ma[i][j]>='A'&&ma[i][j]<='Z'){
                int tx=i,ty=j,f=1,x=i,y=j;
                for(int ia=1;ia<=k;++ia){
                    if(a[ia].d=='N')        tx-=a[ia].s;
                    else if(a[ia].d=='S')   tx+=a[ia].s;
                    else if(a[ia].d=='W')   ty-=a[ia].s;
                    else                    ty+=a[ia].s;
                    if(tx<1||tx>n||ty<1||ty>m||ma[tx][ty]=='#'){
                            f=0;break;
                    }
                    if(y==ty){
                        if(pr[x][y]-pr[tx-1][ty]!=0){
                            f=0;break;
                        }
                    }
                    if(x==tx){
                        if(ps[x][y]-ps[tx][ty-1]!=0){
                             f=0;break;
                        }
                    }
                    x=tx,y=ty;
                }if(f) ans[cnt++]=ma[i][j];
            }
        }
    }
    if(!cnt){
        printf("no solution\n");return 0;
    }
    sort(ans,ans+cnt);
    for(int i=0;i<cnt;++i)printf("%c",ans[i]);
    puts("");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值