• NOIP2009 题解


    潜伏者

    题解:

    简单的字符串模拟,是一道签到题。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+7;
    char s1[maxn];
    char s2[maxn];
    char p[maxn];
    int mp[maxn];
    int mp1[maxn];
    int main(){
        scanf("%s",s1+1);
        scanf("%s",s2+1);
        scanf("%s",p+1);
        int len=strlen(s1+1);
        int len2=strlen(p+1);
        for(int i=1;i<=len;i++){
            if(!mp[s1[i]-'A'+1]) mp[s1[i]-'A'+1]=s2[i]-'A'+1;
            else{
                if(mp[s1[i]-'A'+1]!=s2[i]-'A'+1){
                    printf("Failed
    ");
                    return 0;
                }
            }
            if(!mp1[s2[i]-'A'+1]) mp1[s2[i]-'A'+1]=s1[i]-'A'+1;
            else{
                if(mp1[s2[i]-'A'+1]!=s1[i]-'A'+1){
                    printf("Failed
    ");
                    return 0;
                }
            }
        }
        for(int i=1;i<=26;i++){
            if(!mp[i]){
                printf("Failed
    ");
                return 0;
            }
        } 
        for(int i=1;i<=len2;i++) printf("%c",mp[p[i]-'A'+1]+'A'-1);
        printf("
    ");
        return 0;
    }
    View Code

    hankson的趣味题

    题解:

    50分暴力有手就能写,但是我们肯定要想正解。

    100分正解:还是不太容易想到,参考了一本通上的做法。

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    int tot;
    int n;
    int a0,a1,b0,b1; 
    int gcd(int a,int b){
        if(!b) return a;
        return gcd(b,a%b);
    }
    int lcm(int a,int b){
        return a*b/gcd(a,b);
    }
    signed main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            tot=0;
            scanf("%lld%lld%lld%lld",&a0,&a1,&b0,&b1);
            if(b1%b0){
                printf("0
    ");
                continue;
            }
            int x;
            for(int j=1;j<sqrt(b0);j++){
                if(b0%j==0){
                    x=(b1/b0)*j;
                    if(gcd(x,b0)==j&&gcd(x,a0)==a1) tot++;
                    x=(b1/b0)*(b0/j);
                    if(gcd(x,b0)==b0/j&&gcd(x,a0)==a1) tot++;
                }
            }
            int k=(int)sqrt(b0);
            if(k*k==b0&&b0%k==0){
                x=(b1/b0)*k;
                if(gcd(x,b0)==k&&gcd(x,a0)==a1) tot++;
            }
            printf("%lld
    ",tot);
        }
        return 0;
    }
    View Code

    最优贸易

    题解:

    暑假讲过这道题,思想非常常见,有向图建反边,然后更新最大值最小值即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+7;
    const int INF=0x3f3f3f3f;
    struct node{
        int nxt;
        int to;
    }edge[maxn*2];
    struct node1{
        int nxt;
        int to;
    }edge1[maxn*2];
    int x,y,z;
    int n,m; 
    int head[maxn],cnt;
    int val[maxn];
    int mi[maxn],mx[maxn];
    bool vis[maxn];
    void add(int x,int y){
        edge[++cnt].nxt=head[x];
        edge[cnt].to=y;
        head[x]=cnt;
    }
    int head2[maxn],cnt2;
    void add2(int x,int y){
        edge1[++cnt2].nxt=head2[x];
        edge1[cnt2].to=y;
        head2[x]=cnt2;
    }
    queue<int> q;
    void spfa1(){
        for(int i=1;i<=n;i++){
            mi[i]=INF;
            vis[i]=false;
        }
        mi[1]=val[1];
        q.push(1);
        vis[1]=true;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i;i=edge[i].nxt){
                int v=edge[i].to;
                if(mi[v]>min(mi[u],val[v])){
                    mi[v]=min(mi[u],val[v]);
                    if(!vis[v]){
                        q.push(v);
                        vis[v]=true;
                    }
                }
            }
        }
    }
    void spfa2(){
        for(int i=1;i<=n;i++){
            mx[i]=-INF;
            vis[i]=false;
        }
        mx[n]=val[n];
        q.push(n);
        vis[n]=true;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head2[u];i;i=edge1[i].nxt){
                int v=edge1[i].to;
                if(mx[v]<max(mx[u],val[v])){
                    mx[v]=max(mx[u],val[v]);
                    if(!vis[v]){
                        q.push(v);
                        vis[v]=true;
                    }
                }
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&val[i]);
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            if(z==1){
                add(x,y);
                add2(y,x);
            } 
            else{
                add(x,y);
                add(y,x);
                add2(x,y);
                add2(y,x); 
            }
        }
        spfa1();
        spfa2();
        int ans=0;
        for(int i=1;i<=n;i++){
            ans=max(ans,mx[i]-mi[i]);
        } 
        printf("%d
    ",ans);
        return 0;
    } 
    View Code

    靶形数独

    题解:

    一开始我写的是50分的填数独,非常naive。

    这题是一道搜索好题。网上常有的方法是二进制判断,但我只会稍微剪枝而已。

    对于此题已经足够了,换一种搜索方式,枚举剩下多少格子没有填。然后每次可以枚举一下判断下次该填那个格子。有一个贪心的思路就是每次枚举可填的数最少的格子。这样能有效减少状态分枝。

    #include<bits/stdc++.h>
    using namespace std;
    int sudoku[150][150]; 
    int score[10][10]{
        {0,0,0,0,0,0,0,0,0,0},
        {0,6,6,6,6,6,6,6,6,6},
        {0,6,7,7,7,7,7,7,7,6},
        {0,6,7,8,8,8,8,8,7,6},
        {0,6,7,8,9,9,9,8,7,6},
        {0,6,7,8,9,10,9,8,7,6},
        {0,6,7,8,9,9,9,8,7,6},
        {0,6,7,8,8,8,8,8,7,6},
        {0,6,7,7,7,7,7,7,7,6},
        {0,6,6,6,6,6,6,6,6,6}, 
    };
    int line[150][150];
    int row[150][150];
    int area[150][150];
    long long maxx;
    long long sum;
    int tot;
    void dfs(int rest,long long all){
        if(!rest){
            maxx=max(maxx,all);
            return;
        }
        int sss=19260817,xx,yy,step;
        for(int i=1;i<=9;i++){
            for(int j=1;j<=9;j++){
                if(!sudoku[i][j]){
                    step=0;
                    for(int k=1;k<=9;k++){
                        if(!line[j][k]&&!row[i][k]&&!area[(i-1)/3*3+(j-1)/3+1][k]) step++; 
                    }
                    if(step<sss){
                        sss=step;
                        xx=i;
                        yy=j;
                    }
                }
            }
        }
        for(int i=1;i<=9;i++){
            if(!line[yy][i]&&!row[xx][i]&&!area[(xx-1)/3*3+(yy-1)/3+1][i]&&!sudoku[xx][yy]){
                line[yy][i]=true;
                row[xx][i]=true;
                area[(xx-1)/3*3+(yy-1)/3+1][i]=true;
                sudoku[xx][yy]=i;
                all+=sudoku[xx][yy]*score[xx][yy];
                dfs(rest-1,all);
                line[yy][i]=false;
                row[xx][i]=false;
                area[(xx-1)/3*3+(yy-1)/3+1][i]=false;
                all-=sudoku[xx][yy]*score[xx][yy];
                sudoku[xx][yy]=0;
            }
        }
    }
    int main(){
        maxx=-1;
        for(int i=1;i<=9;i++){
            for(int j=1;j<=9;j++){
                scanf("%d",&sudoku[i][j]);
                if(sudoku[i][j]){
                    tot++;
                    line[j][sudoku[i][j]]=true;
                    row[i][sudoku[i][j]]=true;
                    area[(i-1)/3*3+(j-1)/3+1][sudoku[i][j]]=true;
                    sum+=score[i][j]*sudoku[i][j];
                }
            }
        } 
        dfs(81-tot,sum);//还有多少空格 
        printf("%d
    ",maxx);
        return 0;
    }
    View Code
  • 相关阅读:
    [中文翻译] ASP.NET 5 简介(Introducing ASP.NET 5,原作ScottGu 2015/2/23)
    会写网页 就会写手机APP #2-- 范例修正 , Hybrid Mobile Apps for ASP.NET Developers (Apache Cordova)
    vue事件处理
    vue渲染
    vue数组和对象方法
    vue样式绑定
    vue模板语法与绑定指令
    墨刀的使用
    ajax基础一
    解构赋值中圆括号问题及解构赋值的用途
  • 原文地址:https://www.cnblogs.com/LJB666/p/11802644.html
Copyright © 2020-2023  润新知