【陕西科技大学第一届程序设计比赛—正式赛】 D E G H J K L S

27 篇文章 0 订阅
22 篇文章 0 订阅

PS 过的人太多的就不贴代码了(当然过的人很少的我也不会QAQ,有的题如果能够补过的话,还会更新)

D 三体——人类的末日之战

分析:很明显的 bfs+状态压缩

#include<bits/stdc++.h>
using namespace std;
#define LL long long

const int N = 200+11;
const int M = 1e6+11;
int to[4][2]={1,0,-1,0,0,1,0,-1};
int mp[N][N];  int n,m;
bool vis[N][N][1<<9];
struct Node{
    int x,y,state,step;
};
int cnt;
void bfs(Node st){
    queue<Node>que;
    memset(vis,0,sizeof(vis));
    vis[st.x][st.y][st.state]=1;
    que.push(st);
    while(!que.empty()){
        Node now=que.front(); que.pop();

        for(int i=0;i<4;i++){
            int nx=now.x+to[i][0]; int ny=now.y+to[i][1];
            if(nx<=0||nx>n ||ny<=0||ny>m) continue;

            if(now.state == (1<<cnt)-1 ) {
                printf("%d\n",now.step);
                return ;
            }

            if(mp[nx][ny]>=1 && mp[nx][ny]<=cnt) {
                if(vis[nx][ny][now.state]) continue;
                vis[nx][ny][now.state]=1;
                Node ne={nx,ny,now.state|(1<<(mp[nx][ny]-1)),now.step+1};
                que.push(ne);
                continue;
            }
            if(vis[nx][ny][now.state]) continue;
            vis[nx][ny][now.state]=1;
            Node ne={nx,ny,now.state,now.step+1};
            que.push(ne);
        }
    }
}

int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m); string s;
        Node st;
        cnt=0;
        for(int i=1;i<=n;i++){
            cin>>s;
            for(int j=0;j<m;j++){
               if(s[j]=='W') {
                mp[i][j+1]=0;
                st.x=i; st.y=j+1; st.state=0; st.step=0;
               }else if(s[j]=='S') {
                 mp[i][j+1]=++cnt;
               }else if(s[j]=='#') {
                 mp[i][j+1]=0;
               }
            }
        }
        /*
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++)
                printf("%d",mp[i][j]);
            puts("");
        }*/
        bfs(st);
    }
return 0;
}

E 豆落谁家

分析:dfs 暴力 ,收敛的很快
代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
typedef pair<int,int>pii;

const int N = 1e5+11;
const int M = 1e6+11;

double cnt,p;
void dfs(int num,double gai,int a,int b){
    if(num>50) return ;
    if(b==0) p+=gai;
    if(a==0 || b==0){
        cnt+=num*gai;
        return ;
    }

    int mn=min(a,b);
    dfs(num+1,gai*0.5,a-mn,b+mn);
    dfs(num+1,gai*0.5,a+mn,b-mn);
}

int main(){
    int T ;scanf("%d",&T); int cas=1;
    while(T--){
        int n,m;
        scanf("%d%d",&m,&n);
        cnt=p=0;
        dfs(0,1,m,n);
        printf("Case %d:%.6lf %.6lf\n",cas++,cnt,p);
    }
return 0;
}

问题 G: 战争联盟

分析: 带权并查集
我们维护 每个节点到根节点的距离 ,这样的话在同一个树上的两个点,如果他们到根节点的距离都是奇数或者都是偶数,那么肯定是同一个联盟,反之不是。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
typedef pair<int,int>pii;

const int N = 2e5+11;
const int M = 1e6+11;
const int inf = 0x3f3f3f3f;

int pre[N],relation[N];
void init(int n){
    for(int i=0;i<=n;i++){
        pre[i]=i;
        relation[i]=0;
    }
}

int Find(int x){
    if(x==pre[x]) return x;
    int t=pre[x];
    pre[x]=Find(pre[x]);
    relation[x]= relation[x]+relation[t]; // 路径压缩
    return pre[x];
}

void Join(int x,int y){
    int tx=Find(x); int ty=Find(y);
    if(tx!=ty){
        relation[tx]=relation[y]+1-relation[x];
        pre[tx]=ty;
    }
}

int main(){
    int t;scanf("%d",&t);
    while(t--){
        int n,k; scanf("%d%d",&n,&k);
        init(n);
        while(k--){
            char s[2];int a,b; scanf("%s %d %d",s,&a,&b);
            if(s[0]=='A'){
                if(Find(a)==Find(b)) {
                    if( (relation[a]+relation[b]) &1) puts("Belong to different group.");
                    else puts("Belong to same group.");
                }else  puts("Not sure yet.");
            }else Join(a,b);
        }
    }
return 0;
}

H 贴瓷砖

分析:暴力就好(不过要提前预处理 每一行和每一列的前缀和)
时间复杂度o(n*n*n)

#include<bits/stdc++.h>
using namespace std;
#define LL long long


const int N = 300+11;
int mp[N][N];
int row[N][N];
int vol[N][N];
LL ans[N];
int main(){
    int n;
    while(cin>>n){
        if(!n) break;
        memset(row,0,sizeof(row));
        memset(vol,0,sizeof(vol));
        memset(ans,0,sizeof(ans));
        memset(mp,0,sizeof(mp));
        for(int i=1;i<=n;i++){
            getchar();
            for(int j=1;j<=n;j++){
                char zz;
                scanf("%c",&zz);
                mp[i][j]=zz-'0';
            }
        }

        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                row[i][j]=row[i][j-1]+mp[i][j];
                vol[i][j]=vol[i-1][j]+mp[i][j];
            }
        }

        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(mp[i][j]==0) continue;
                for(int k=2;k<=n;k++){
                    int z=j+k-1; if(z>n) break;
                    if(row[i][z]-row[i][j-1] == k) {
                        int zz=i+k-1; if(zz>n) break;
                        if(vol[zz][j]-vol[i-1][j]==k) {
                            if(vol[zz][z]-vol[i-1][z] == k) {
                                 if(row[zz][z]-row[zz][j-1] == k) {
                                    ans[k]++;
                                 }else break;
                            }else break;
                        }else break;
                    }else break;
                }
            }
        }
        for(int i=2;i<=n;i++){
            if(ans[i]==0) continue;
            printf("%d %lld\n",i,ans[i]);
        }
        puts("");
    }
return 0;
}

J 飓风营救小灰灰

分析:直接BFS模拟就好

#include<bits/stdc++.h>
using namespace std;
#define LL long long
typedef pair<int,int>pii;

const int N = 100+11;
const int M = 1e6+11;
int to[4][2]={1,0,-1,0,0,1,0,-1};
int mp[N][N]; int n,m,c;
bool vis[N][N];
vector<pii>ve[10];

struct Node{
    int x,y ,step;
};
void bfs(Node st){
    queue<Node>que;
    memset(vis,0,sizeof(vis));
    que.push(st);
    while(!que.empty()){
        Node now=que.front();que.pop();
        for(int i=0;i<4;i++){
            int nx=now.x+to[i][0]; int ny=now.y+to[i][1];
            if(nx<=0||nx>n||ny<=0||ny>m) continue;
            if(mp[nx][ny]==12) continue;
            if(vis[nx][ny]) continue;

            if(mp[nx][ny]==10) {
                printf("%d\n",now.step+1+1);
                return ;
            }
            if(mp[nx][ny]>=0 && mp[nx][ny]<=c){
                int v=mp[nx][ny];
                for(int j=0;j<ve[v].size();j++){
                    pii p=ve[v][j];
                    if( p.first==nx && p.second==ny) continue;
                    Node ne={p.first,p.second,now.step+1};
                    que.push(ne);
                }
                vis[nx][ny]=1;
            }

            Node ne={nx,ny,now.step+1};
            vis[nx][ny]=1;
            que.push(ne);
        }
    }
    puts("Trapped!");
}

int main(){

    while(scanf("%d%d%d",&m,&n,&c)) {
        for(int i=0;i<10;i++) ve[i].clear();
        if(n==m&&n==c&&n==0) break;
        string s;
        Node st,ed;
        for(int i=1;i<=n;i++){
            cin>>s;
            for(int j=0;j<m;j++){
               if(s[j]=='S') {
                mp[i][j+1]=11;
                st.x=i; st.y=j+1; st.step=0;
               }else if(s[j]=='E'){
                 ed.x=i; ed.y=j+1;ed.step=0;
                 mp[i][j+1]=10;
               }else if(s[j]=='#' || s[j]=='M') {
                 mp[i][j+1]=12;
               } else if(s[j]=='*') mp[i][j+1]=11;
               else {
                    mp[i][j+1]=s[j]-'0';
                    int val=s[j]-'0';
                    ve[val].push_back(make_pair(i,j+1)) ;
               }
            }
        }

        /*
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++)
                printf("%d  ",mp[i][j]);
            puts("");
        }
        */
        bfs(st);
    }


return 0;
}

K 数字拼图

分析:百度直接搜 拼图游戏 很多解释的。
代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long


const int N = 10+11;
const int M = 1e6+11;
const int inf = 0x3f3f3f3f;


int a[N*N],sz;
int main(){
    int n;
    while(cin>>n){
        if(!n) break;
        sz=0;int Pb=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
               int zz; cin>>zz;
                if(zz==0){
                     a[sz++]=inf;
                     Pb+=i+j;
                }
                else a[sz++]=zz;
            }
        }

        int Pa=n+n;
        for(int i=0;i<sz;i++){
            for(int j=0;j<i;j++) {
                if(a[j]>a[i]) Pb++;
            }
        }
        if((Pb+Pa)&1) puts("NO");  //  原图和目标图的 奇偶一定要相同
        else puts("YES");
    }

return 0;
}

L Fehead的项目

分析: 对于任意一个区间来说,其面积为 区间中最小值*区间长度,所以直接建立一颗线段树维护就ok了
代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
typedef pair<int,int>pii;

const int N = 100000+11;
const int M = 1e6+11;
const int inf = 0x3f3f3f3f;

struct Tree{
    int le,ri,len;
    LL mn,mx;
}tree[N<<2];
void Up(int o){
    tree[o].mn=min(tree[o<<1].mn,tree[o<<1|1].mn);
    tree[o].mx=max(tree[o<<1].mx,tree[o<<1|1].mx);
    tree[o].mx=max(tree[o].mx,tree[o].len*tree[o].mn);
}
void Build(int o,int le,int ri){
     tree[o].le=le;tree[o].ri=ri; tree[o].len=ri-le+1;
     if(le==ri){
        LL val;
        scanf("%lld",&val);
        tree[o].mn=tree[o].mx=val;
        return ;
     }
     int mid=(le+ri)>>1;
    Build(o<<1,le,mid);
    Build(o<<1|1,mid+1,ri);
    Up(o);
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF && n){
        Build(1,1,n);
        printf("%lld\n",tree[1].mx);
    }
return 0;
}

S 躁动的小Z

分析:求最短路的同时直接维护一下前驱就行了。
代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define LL long long

const int N = 1e5+11;
const int M = 1e6;
const int mod = 7653;
const int inf = 0x3f3f3f3f;
const double E = exp(1.0);

struct Edge{
    int from,to,val,next;
}edge[M];
int head[N],top;
void init(){
    memset(head,-1,sizeof(head));
    top=0;
}
void addedge(int a,int b,int c){
    Edge e={a,b,c,head[a]};
    edge[top]=e; head[a]=top++;
}
int dis[N]; bool vis[N];
int pre[N];
void spfa(int st){
    queue<int>Q;
    memset(dis,inf,sizeof(dis));
    memset(vis,false,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    Q.push(st); vis[st]=true; dis[st]=0;
    while(!Q.empty()){
        int now=Q.front();Q.pop();vis[now]=false;
        for(int i=head[now];i!=-1;i=edge[i].next){
            Edge e=edge[i];
            if(dis[e.to]>dis[now]+e.val){
                dis[e.to]=dis[now]+e.val;
                pre[e.to]=now;
                if(!vis[e.to]){
                    vis[e.to]=true;
                    Q.push(e.to);
                }
            }
        }
    }
}
int have;
void OutPut(int now){
    if(now==-1) return ;
    OutPut(pre[now]);
    if(have++) putchar(' ');
    printf("%d",now);
}
int main(){
     int n,m;
     while(scanf("%d%d",&n,&m)!=EOF){
        init();
        for(int i=1;i<=m;i++){
            int a,b,c;scanf("%d%d%d",&a,&b,&c);
            addedge(a,b,c);
            addedge(b,a,c);
        }
        spfa(1);
       // for(int i=1;i<=n;i++) printf("%d ",pre[i]);
        if(dis[n]>=inf) puts("-1");
        else  {
            have=0;
            OutPut(n);
            puts("");
        }
     }
return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值