bzoj1784: [Usaco2010 Jan]island

现在居然出现一道题只有\(pascal\)题解没有\(C++\)题解的情况,小蒟蒻要打破它。

思维题:分类讨论

回归正题,此题十分考验思维,首先我们要考虑如何把不会走的地方给填上,使最后只用求一遍这个图的周长即可。考虑目标点的几种情况:

\(0.\)当前点周围有三个\(A\)或四个\(A\)时:这个点肯定不会走到,直接用\(A\)填上。

\(1.\)当前点夹在两个点中间,无法判断这个点被填上后是否会让两边出现独立的\(x\),所以跳过该点,之后如果某一边被填满,会导致这个点被重新搜到,那时再考虑。

\(2.\)当前点被两个相邻的\(A\)夹在一起,且当前点填上时周围八格没有任何\(x\),那么直接填上。

\(3.\)当前点被两个相邻的\(A\)夹在一起,且当前点填上时周围八格有\(x\)那么这个点肯定会被经过,因为无论往外怎么伸展,最后必须从这里过去以绕开那个\(x\)。

\(4.\)当前点周围有一个\(A\)或没有\(A\),那么这个点先不管,等会也可能再次搜到。

复杂度证明:因为每个点只会有一次变成\(A\)然后向外搜索,所以复杂度为\(O(nm)\)

对于处理出来的图,我们只用判断每个点会被经过几次就行了:每个点经过的次数等于这个点周围\(八格\)的连续\(A\)段数。

最后上神奇的代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
int n,m;
char mp[N][N];
void dfs(int x,int y){
    int cnt=0;
    int u[5];
    for(int i=0;i<4;++i){
        int nx=x+dx[i],ny=y+dy[i];
        if(mp[nx][ny]=='A'){
            u[++cnt]=i;
        }
    }
    if(cnt==2){
        if(u[2]-u[1]==2)return;
        if(mp[x-dx[u[1]]-dx[u[2]]][y-dy[u[1]]-dy[u[2]]]!='.')return;
    }
    if(cnt>1){
        mp[x][y]='A';
        for(int i=0;i<4;++i){
            int nx=x+dx[i],ny=y+dy[i];
            if(nx>1&&nx<n&&ny>1&&ny<m&&mp[nx][ny]=='.'){
                dfs(nx,ny);
            }
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        scanf("%s",mp[i]+1);
    }
    for(int i=2;i<n;++i){
        for(int j=2;j<m;++j){
            if(mp[i][j]=='.')dfs(i,j);
        }
    }
    int ans=0;
    for(int x=1;x<=n;++x){
        for(int y=1;y<=m;++y){
            int js=0;
            if(mp[x][y]=='.'){
                int u[5],cnt=0;
                for(int i=0;i<4;++i){
                    int nx=x+dx[i],ny=y+dy[i];
                    if(mp[nx][ny]=='A')u[++cnt]=i;
                }
                if(cnt==1){
                    js=1;
                }else if(cnt==2&&abs(u[2]-u[1])==2){
                    js=2;
                }else if(cnt==2)js=1;
                for(int i=0;i<4;++i){
                    int nx=x+dx[i],ny=y+dy[i];
                    if(mp[nx][ny]!='A'){
                        nx=x+dx[(i+1)%4],ny=y+dy[(i+1)%4];
                        if(mp[nx][ny]!='A'){
                            nx=x+dx[i]+dx[(i+1)%4],ny=y+dy[i]+dy[(i+1)%4];
                            if(mp[nx][ny]=='A'){
                                js++;
                            }
                        }
                    }
                }
                ans+=js;
            }
        }
    }
    cout<<ans<<endl;
}

原文地址:https://www.cnblogs.com/zhenglier/p/11122222.html

时间: 2024-08-29 17:08:32

bzoj1784: [Usaco2010 Jan]island的相关文章

BZOJ2021: [Usaco2010 Jan]Cheese Towers

2021: [Usaco2010 Jan]Cheese Towers Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 184  Solved: 107[Submit][Status] Description Farmer John wants to save some blocks of his cows' delicious Wisconsin cheese varieties in his cellar for the coming winter.

2020: [Usaco2010 Jan]Buying Feed, II

2020: [Usaco2010 Jan]Buying Feed, II Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 220  Solved: 162[Submit][Status] Description (buying.pas/buying.in/buying.out 128M 1S) Farmer John needs to travel to town to pick up K (1 <= K <= 100) pounds of feed

bzoj 1783: [Usaco2010 Jan]Taking Turns

1783: [Usaco2010 Jan]Taking Turns Description Farmer John has invented a new way of feeding his cows. He lays out N (1 <= N <= 700,000) hay bales conveniently numbered 1..N in a long line in the barn. Hay bale i has weight W_i (1 <= W_i <= 2,0

BZOJ 2021 Usaco2010 Jan Cheese Towers 动态规划

题目大意:完全背包,如果最顶端的物品重量≥k,那么下面的所有物品的重量变为原来的45 考虑一些物品装进背包,显然我要把所有重量大于≥k的物品中重量最小的那个放在最顶端,才能保证总重量最小 那么我们给物品排个序,第一键值为重量是否≥k(≥k的放在前面),第二键值为重量(从小到大) 然后依次加入背包,令fi表示没有重量≥k的物品放在最顶端时重量为i的最大价值,gi表示有重量≥k的物品放在最顶端是重量为i的最大价值,DP即可 时间复杂度O(nT) #include <cstdio> #include

BZOJ1783: [Usaco2010 Jan]Taking Turns

n<=700000个数,两人轮流取数,位置必须单增,输出两人都按最优策略得到的最大答案. 一开始看不懂"最优策略",后来发现没有必要知道,f[i][1/0]--先/后手取数i最优答案,f[i][1]=a[i]+f[maxi][0],f[i][0]=f[maxi][1],maxi>i,因为先手取完后手必定转移到后面最优的先手策略. 然后WA了一发.这两人还是挺友好的不会陷害对方,就是说,有多个f[maxi][1]时,去下标最小的一个,让游戏进行地更持久! 1 #include

bzoj usaco 金组水题题解(1)

UPD:我真不是想骗访问量TAT..一开始没注意总长度写着写着网页崩了王仓(其实中午的时候就时常开始卡了= =)....损失了2h(幸好长一点的都单独开了一篇)....吓得赶紧分成两坨....TAT.............. —————————————————————————————————————————————————————————————————————————————— 写(被虐)了整整一个月b站上usaco的金组题...然而到现在总共只写了100道上下TAT(当然是按AC人数降序排

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734

小结:动态规划

概要: 状态.转移:最优子结构.无后效性. 技巧及注意: dp就是纯经验+智商题 在dp方程写出来后,一定要考虑边界!不要以为转移对了就行了! 滚动数组的话一定要考虑好顺序! 下标有时候可以灵活使用!比如mod意义下的dp,倍数什么.可到达性等题目都可以这样做. 如果是线性序列的max{f[k]},k<i这种可以用线段树或bit维护成log 注意“前i”和“第i”的区别(特别对于答案更新),有时换一种就能解答出问题. 在状态加限制条件,如单调.地址等. 用下标来维护下标这个答案是否可达. 博弈论

light oj 1265 - Island of Survival(概率dp)

1265 - Island of Survival PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB You are in a reality show, and the show is way too real that they threw into an island. Only two kinds of animals are in the island, the tigers and t