2017.11.08离线赛总结

river ——3817

思路:这是一道十分骚的题目…首先,我也不知道我的暴力bfs只有20分…然而实际是爆零的——格式错误(输出一行,最后没空格且有换行T_T)。
正解也是挺简单的,预处理每个点两次dfs就够了,第1次dfs染色+找边界,
第2次算步数。

code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define db double
#define INF 0x3f3f3f3f
#define inf 0x7fffffff
#define pb push_back
#define Sz(a) sizeof(a)
#define mcl(a,b) memset(a,b,Sz(a))
#define mcp(a,b) memcpy(a,b,Sz(b))

#define N 1005

int n,m,ans;
int A[N][N];
int dx[]={-1,-1,-1,0,0,1,1,1};
int dy[]={-1,0,1,-1,1,-1,0,1};

bool check(int x,int y){return x<0 || x>n || y<0 || y>n;}
bool check_done(int x,int y){return x==1 || x==n || y==1 || y==n;}

struct p40{
    struct node{
        int x,y,step;
    };
    bool vis[N][N];
    int bfs(int sx,int sy){
        queue<node>Q;
        while(!Q.empty())Q.pop();
        Q.push((node){sx,sy,0});
        int ans=INF;
        while(!Q.empty()){
            node now=Q.front();Q.pop();
            if(check_done(now.x,now.y)){
                ans=min(ans,now.step);
                continue;
            }
            REP(i,0,7){
                int nx=now.x+dx[i];
                int ny=now.y+dy[i];
                if(check(nx,ny))continue;
                if(vis[nx][ny])continue;
                vis[nx][ny]=1;
                node nxt;
                nxt.x=nx,nxt.y=ny,nxt.step=now.step;
                if(A[nx][ny]==1 && A[now.x][now.y]==0)nxt.step++;
                Q.push(nxt);
            }
        }
        return ans;
    }
    void solve(){
        REP(i,1,m){
            int x,y;
            scanf("%d%d",&x,&y);
            memset(vis,0,Sz(vis));
            printf("%d",bfs(x,y));
            if(i!=m)putchar(' ');
        }
        puts("");
    }
}p40;
struct p100{
    int mark[N][N];
    int ans[N][N];
    int Min;
    void dfs(int x,int y,int col){
        mark[x][y]=1;
        if(x==1||x==n||y==1||y==n)Min=0;
        REP(i,0,7){
            int nx=dx[i]+x,ny=dy[i]+y;
            if(check(nx,ny))continue;
            if(ans[nx][ny]!=-1)Min=min(Min,ans[nx][ny]+(A[nx][ny]==1 && A[x][y]==0));
            if(mark[nx][ny]!=0 || A[x][y]!=A[nx][ny])continue;
            dfs(nx,ny,col);
        }
    }

    void Dfs(int x,int y){
        ans[x][y]=Min;
        mark[x][y]=-1;
        REP(i,0,7){
            int nx=dx[i]+x,ny=dy[i]+y;
            if(mark[nx][ny]!=1)continue;
            Dfs(nx,ny);
        }
    }

    void solve(){
        mcl(ans,-1);
        REP(i,1,n){
            REP(j,1,n){
                if(mark[i][j])continue;
                Min=INF;
                dfs(i,j,A[i][j]);
                Dfs(i,j);
            }
        }
        REP(i,1,m){
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%d",ans[a][b]);
            if(i!=m)putchar(' ');
        }
        puts("");
    }
}p100;
char s[N];
int main(){
//  freopen("river.in","r",stdin);
//  freopen("river.out","w",stdout);
//  printf("%d\n",(Sz(p100)+Sz(p40))/1024/1024);
    cin>>n>>m;
    REP(i,1,n){
        scanf("%s",s+1);
        REP(j,1,n)A[i][j]=(s[j]=='1');
    }
    if(n<=10)p40.solve();
    else p100.solve();
    return 0;
}

resource ——3818

思路:暴力30;
正解应该是计算出每个颜色对每个格子的贡献,
据题意知,颜色只有出现1次才有用,也就是说第2次出现时没用的,
那么就可以根据上一次该颜色出现的位置和当前颜色出现的位置,那么贡献的长度为posj-posi,len应该是扫描时加过来的。
但最后还有第一次和第二之间的答案没有累加,最后再扫描一遍补上。

code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define db double
#define INF 0x3f3f3f3f
#define inf 0x7fffffff
#define pb push_back
#define Sz(a) sizeof(a)
#define mcl(a,b) memset(a,b,Sz(a))
#define mcp(a,b) memcpy(a,b,Sz(b))

#define N 1105
#define P 19900907

int n,m;

struct p30{
    int A[N][N];
    LL ans;
    int cnt[105];
    void work(int x,int y){
        mcl(cnt,0);
        REP(i,1,x)REP(j,1,y)cnt[A[i][j]]++;
        REP(i,0,100)if(cnt[i]==1)ans++,ans%=P;
    }
    void solve(){
        REP(i,1,n)REP(j,1,m)scanf("%d",&A[i][j]);
        ans=0;
        REP(i,1,n)
            REP(j,1,m)
                work(i,j);
        cout<<ans<<endl;
    }
}p30;
struct p100{
    int pos1[N*N],pos2[N*N],len[N*N];
    void solve(){
        LL ans=0;
        REP(i,1,n)REP(j,1,m){
            int col;scanf("%d",&col);
            if(!len[col]){  
                len[col]=i;  
                pos1[col]=j;  
                pos2[col]=m+1;  
                continue;  
            }  
            if (j<pos1[col]){  
                ans+=1LL*(i-len[col])*(pos2[col]-pos1[col])%P,ans%=P;  
                pos2[col]=pos1[col];  
                pos1[col]=j;  
                len[col]=i;  
            } else if (j<pos2[col]){  
                ans+=1LL*(i-len[col])*(pos2[col]-j)%P,ans%=P;  
                pos2[col]=j;  
            }   
        }  
        REP(i,1,n*m)if(len[i])ans+=1LL*(n+1-len[i])*(pos2[i]-pos1[i])%P,ans%=P;  
        cout<<ans<<endl;
    }
}p100;
int main(){
//  freopen("resource.in","r",stdin);
//  freopen("resource.out","w",stdout);
//  printf("%d\n",(Sz(A)+Sz(p100)+Sz(p30))/1024/1024);
    cin>>n>>m;
    if(n<=100 && m<=100)p30.solve();
    else p100.solve();
    return 0;
}

landcraft ——3819

思路:这是一道十分水的最短路题…
题意是算出最小时间,但是根据题意知道,最短路还不够,还要去一个城市的结界城市,并走到那;
也就是说,ans=max(dis[n],炸掉n的结界城市的最迟时间)。
而dis[i]又会被城市i的结界城市所影响,所以另外应该记录到i的最迟时间。
最后就是通过Dijkstra跑最短路即可。

code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define db double
#define INF 0x3f3f3f3f
#define inf 1e15
#define pb push_back
#define Sz(a) sizeof(a)
#define mcl(a,b) memset(a,b,Sz(a))
#define mcp(a,b) memcpy(a,b,Sz(b))

#define N 3005

int n,m;
int num[N];
struct node{
    int to;
    LL cost;   
    bool operator <(const node &_) const{
        return cost>_.cost;    
    }
};
vector<node>E[N];
vector<int>G[N];
priority_queue<node>Q;
LL dis[N],d[N][2];
bool vis[N];
void Dijkstra(){
    REP(i,1,n)dis[i]=d[i][0]=d[i][1]=inf;
    REP(i,1,n)if(!num[i])d[i][1]=0;
    d[1][0]=0;dis[1]=0;
    Q.push((node){1,0});
    while(!Q.empty()){
        node q=Q.top();
        Q.pop();
        int x=q.to;
        if(vis[x])continue;
        vis[x]=1;
        REP(i,0,G[x].size()-1){
            int y=G[x][i];num[y]--;
            if(d[y][1]==inf)d[y][1]=dis[x];
            else d[y][1]=max(d[y][1],dis[x]);
            dis[y]=max(d[y][1],d[y][0]);
            if(!num[y]&&dis[y]!=inf)Q.push((node){y,dis[y]});
        }
        REP(i,0,E[x].size()-1){
            int y=E[x][i].to;
            if(vis[y])continue;
            if(d[y][0]>dis[x]+E[x][i].cost && !num[y]){
                d[y][0]=dis[x]+E[x][i].cost;
                LL t=max(d[y][0],d[y][1]);
                if(dis[y]>t){
                    dis[y]=t;
                    Q.push((node){y,dis[y]});
                }
            }
            else if(d[y][0]>dis[x]+E[x][i].cost)d[y][0]=dis[x]+E[x][i].cost;
        }
    }
}
int main(){
//  freopen("landcraft.in","r",stdin);
//  freopen("landcraft.out","w",stdout);
    cin>>n>>m;
    REP(i,1,m){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        E[a].push_back((node){b,c});
    }
    REP(i,1,n){
        int x;
        scanf("%d",&num[i]);
        REP(j,1,num[i])scanf("%d",&x),G[x].push_back(i);
    }
    Dijkstra();
    printf("%lld\n",dis[n]);    
    return 0;
}

小结:第1题的题目着实坑…简直无解爆零…第2题最后ans没有mod…
还是有一大堆低级错误——考试时应该将note就放在代码旁边…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值