• hihocoder 微软编程之美2015 初赛 第二场(暴力+字典序+图论+思维算法)


    题目1 : 扑克牌

    时间限制:2000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    一副不含王的扑克牌由52张牌组成,由红桃、黑桃、梅花、方块4组牌组成,每组13张不同的面值。现在给定52张牌中的若干张,请计算将它们排成一列,相邻的牌面值不同的方案数。

    牌的表示方法为XY,其中X为面值,为2、3、4、5、6、7、8、9、T、J、Q、K、A中的一个。Y为花色,为S、H、D、C中的一个。如2S、2H、TD等。

    输入

    第一行为一个整数T,为数据组数。

    之后每组数据占一行。这一行首先包含一个整数N,表示给定的牌的张数,接下来N个由空格分隔的字符串,每个字符串长度为2,表示一张牌。每组数据中的扑克牌各不相同。

    输出

    对于每组数据输出一行,形如"Case #X: Y"。X为数据组数,从1开始。Y为可能的方案数,由于答案可能很大,请输出模264之后的值。

    数据范围

    1 ≤ T ≤ 20000

    小数据

    1 ≤ N ≤ 5

    大数据

    1 ≤ N ≤ 52

    样例输入
    5
    1 TC
    2 TC TS
    5 2C AD AC JC JH
    4 AC KC QC JC
    6 AC AD AS JC JD KD
    
    样例输出
    Case #1: 1
    Case #2: 0
    Case #3: 48
    Case #4: 24
    Case #5: 120
    

    算法分析:本题目就是给你n张扑克牌,这些扑克牌的有各自的数值和花色。
    问题:给你n张扑克牌,这n张可以排成很多种序列,求没有两张相邻扑克牌
    的数值相同的方法种类数。
    先看数据,小数据时候n最大等于5。 5!=120,暴力完全可以!
    我们读入n个串,每个串存储在二位数组的一维下标就是它的标号。
    比如:s[0][]: TC  对应0
            s[1][]: TS  对应1
            ......
    这样我们就生成了:0 1 2 ...n-1, 我们将整个序列进行字典序生成,看看
    当下的序列对应串的序列有没有两张扑克牌是相邻的,如果没有表示当下的排列
    是可行的,cnt++;
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <math.h>
    #include <algorithm>
    #define N 5010
    
    using namespace std;
    
    int num(char *s)
    {
        int ans;
        if(s[0]>='2' && s[0]<='9' )
        {
            ans = s[0]-48;
        }
        else if(s[0]=='T') ans =10;
        else if(s[0]=='J') ans =11;
        else if(s[0]=='Q') ans =12;
        else if(s[0]=='K') ans =13;
        else if(s[0]=='A') ans =1;
        return ans;
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        int cnt=1;
    
        int n;
        int i, j, k;
        char s[10][5];
    
        while(t--)
        {
            scanf("%d", &n);
    
            for(i=0; i<n; i++)
            {
                scanf("%s", s[i]);
            }//数据初始化
    
            char str[10]; memset(str, '', sizeof(str));
    
            for(i=0; i<n; i++)
            {
                str[i]=i+48;
            }
            str[n]='';
    
            int ans=0;
            do
            {
                int cur;
                bool flag=true;
                for(i=0; i<n; i++)
                {
                    if(i==0)
                        cur = num( s[str[i]-48] );
                    else
                    {
                        int dd=num(s[str[i]-48] );
                        if(dd == cur){
                            flag=false; break;
                        }
                        else cur = dd;
                    }
                }
                if(flag==true)
                    ans++;
            }
            while(next_permutation(str, str+n));
            printf("Case #%d: %d
    ", cnt++, ans );
    
        }
        return 0;
    }
    

    题目2 我没看~~~

    题目3 : 八卦的小冰

    时间限制:2000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    小冰是个八卦的人,最近她对一个社交网站很感兴趣。

    由于小冰是个机器人,所以当然可以很快地弄清楚这个社交网站中用户的信息啦。

    她发现这个社交网站中有N个用户,用户和用户之间可以进行互动。小冰根据用户之间互动的次数和内容判断每对用户之间的亲密度。亲密度非负,若大于零表示这两个用户之间是好友关系。由于这个网站是活跃的,所以小冰会不停地更新用户之间的亲密度。

    由于隐私保护,小冰无法知道每个用户的确切性别,但是作为一只很聪明的人工智能,小冰可以通过每个用户的行为来猜测性别。当然这种猜测是不准确的,小冰有可能会改变对一个用户的判断。

    小冰想知道这个社交网络的八卦度是多少。八卦度的定义是社交网络中所有异性好友之间的亲密度之和。你能帮助她吗?

    输入

    第一行一个整数T,表示数据组数。接下来是T组数据,每组数据的格式如下:

    第一行是三个整数N, M, Q,分别表示用户数、初始的好友对数、操作数。

    第二行是N个空格隔开的数,第i个数表示i号用户的性别,用0或1表示。

    接下来的M行,每行三个数x, y, z,代表初始状态用户x和用户y之间的亲密度是z。除此之外的用户之间的亲密度初始为0。

    接下来是Q行,每行是以下三种操作中的一种:

    1. “1 x”:改变用户x的性别

    2. “2 x y z”:改变用户x与用户y之间的亲密度为z

    3. “3”:询问八卦度

    输出

    对于每组数据首先输出一行"Case #X:",X为测试数据编号。

    接下来对于每一个询问,输出一行包含询问的八卦度。

    数据范围

    1 ≤ T ≤ 20

    1 ≤ x, y ≤ N

    0 ≤ z ≤ 100000

    小数据

    1 ≤ N, M ≤ 100

    1 ≤ Q ≤ 1000

    大数据

    1 ≤ N, M, Q ≤ 100000

    样例输入
    1
    3 2 8
    0 1 0
    1 2 1
    1 3 1
    3
    1 1
    1 2
    3
    2 2 3 2
    3
    1 2
    3
    
    样例输出
    Case #1:
    1
    2
    2
    3
    

           算法分析:小数据时候很简单,建立二维矩阵存储,每次询问八卦值的时候暴力一遍图,统计计算一下就可以了。

           代码;

           

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <math.h>
    #include <algorithm>
    #define N 5010
    
    using namespace std;
    
    int n, m, q; //三个整数N, M, Q,分别表示用户数、初始的好友对数、操作数。
    
    /*
    第一行是三个整数N, M, Q,分别表示用户数、初始的好友对数、操作数。
    第二行是N个空格隔开的数,第i个数表示i号用户的性别,用0或1表示。
    接下来的M行,每行三个数x, y, z,代表初始状态用户x和用户y之间的
    亲密度是z。除此之外的用户之间的亲密度初始为0。
    接下来是Q行,每行是以下三种操作中的一种:
    
    1. “1 x”:改变用户x的性别
    2. “2 x y z”:改变用户x与用户y之间的亲密度为z
    3. “3”:询问八卦度
    
    */
    
    int map[110][110];
    
    int main()
    {
        int t;
        scanf("%d", &t);
        int cnt=1;
        int sex[110];
    
        while(t--)
        {
            memset(map, 0, sizeof(map));
    
            scanf("%d %d %d", &n, &m, &q);
            for(int i=1; i<=n; i++)
                scanf("%d", &sex[i]);
            int x, y, z;
            for(int i=0; i<m; i++)
            {
                scanf("%d %d %d", &x, &y, &z);
                map[x][y]=z;
                map[y][x]=z;
            }
            printf("Case #%d:
    ", cnt++);
            while(q--)
            {
                int dd;
                scanf("%d", &dd);
                if(dd==1){
                    scanf("%d", &x);
                    sex[x] = sex[x]==0?1:0; //修改性别
                }
                else if(dd==2){
                    scanf("%d %d %d", &x, &y, &z); //改变用户x与用户y之间的亲密度为z
                    map[x][y]=z;
                    map[y][x]=z;
                }
                else{
                    //询问八卦度:社交网络中所有异性好友之间的亲密度之和
                    long long ans=0;
               /*     for(int i=1; i<=n; i++)
                        printf("%d  ", sex[i]);
                    printf("
    "); */
    
                    for(int i=1; i<=n; i++)
                    {
                        for(int j=i+1; j<=n; j++)
                        {
                            if(map[i][j]>0 && (sex[i]+sex[j])==1 ){
                                ans = ans + map[i][j];
                                //map[i][j]=0; map[j][i]=0; //断开关系
                            }
                        }
                    }
                    printf("%lld
    ", ans );
                }
            }
        }
    
        return 0;
    }
    

     大数据的处理方法:

    既然是大数据,可想而知,当每次询问八卦值的时候,不可能每次询问都要再去重新计算一次整个图的八卦值。

    这样做必然会超时!所以我们的思路就是,初始建好图之后,就统计好整个图建图之初的八卦值,以后如果遇到

    询问的话,就直接输出,如果遇到修改图的信息的情况就要动态的修改整个图的八卦值ans。

    1.假设遇到修改节点x的性别,x的性别修改只会影响与之相邻的节点。

    分四种情况:ori(x)=0, cur(x)=1;  //原来性别是0,现在是1

                  与x相邻的节点假设是y:sex(y)=0 或 sex(y)=1

                  也就是说:sex[cur(x) ] + sex[y]  == (1+0=1) 或者 (1+1=2)

                     ori = 1, cur = 0;

                  sex[cur(x) ] + sex[y]  == (0+0=0) 或者 (0+1=1)

                  相加后的值为1的话,说明x修改后两者性别相反,八卦值ans要加上 weight(x-y)的权重。

                  相加后的值为0或2的话,说明x修改后两者性别相反,八卦值ans要减去 (x-y)的权重。

    2.如果修改x-y节点间的权重为z,先看看x-y节点之间之前有没有八卦值(初始默认为0:表示无)。

    如果没有则要添加进去,如果有,修改就好了。如果两者的性别是相同的,修改权值后不会影响当前

    的八卦值ans,如果x-y性别不同则要考虑一下该怎么修改八卦值ans,这个就很简单了,具体不细讲了。

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <math.h>
    #include <vector>
    #include <algorithm>
    #define N 100000+10
    
    using namespace std;
    
    int n, m, q; //三个整数N, M, Q,分别表示用户数、初始的好友对数、操作数。
    
    struct node
    {
        int to;
        int w;
    }temp;
    
    int main()
    {
        int t;
        scanf("%d", &t);
        int cnt=1;
        int sex[N];
    
        while(t--)
        {
            vector<node>qm[N];
            long long ans=0;
    
            scanf("%d %d %d", &n, &m, &q);
            for(int i=1; i<=n; i++)
                scanf("%d", &sex[i]);
            int x, y, z;
            for(int i=0; i<m; i++)
            {
                scanf("%d %d %d", &x, &y, &z);
                if(sex[x]+sex[y]==1 )
                    ans = ans+z;
                temp.to=y; temp.w=z;
                qm[x].push_back(temp);
                temp.to=x;
                qm[y].push_back(temp); //建图
            }
            printf("Case #%d:
    ", cnt++);
            while(q--)
            {
                int dd;
                scanf("%d", &dd);
                if(dd==1){
                    scanf("%d", &x);
                    sex[x] = sex[x]==0?1:0; //修改性别
                    int len;
                    len=qm[x].size();
                    for(int i=0; i<len; i++){
                        if(sex[x]+sex[qm[x][i].to]==1 )
                            ans = ans + qm[x][i].w;
                        else if( sex[x]+sex[qm[x][i].to]==0 )
                            ans = ans - qm[x][i].w;
                        else if( sex[x]+sex[qm[x][i].to]==2 )
                            ans = ans - qm[x][i].w;
                    }
                }
                else if(dd==2){
                    scanf("%d %d %d", &x, &y, &z); //改变用户x与用户y之间的亲密度为z
                    int ori=0, cur=0;
                    int len;
                    len=qm[x].size();
    
                    bool flag=false;
                    for(int i=0; i<len; i++)
                    {
                        if(qm[x][i].to == y){
                                flag=true;
                            ori = qm[x][i].w; //保存一份原来的值
                            qm[x][i].w=z; break;
                        }
                    }
                    if(flag==false){
                        temp.to=y; temp.w=z;
                        qm[x].push_back(temp);
                    }
    
                    len=qm[y].size();
                    flag=false;
                    for(int i=0; i<len; i++)
                    {
                        if(qm[y][i].to == x){
                                flag=true;
                            qm[y][i].w=z; break;
                        }
                    }
                    if(flag==false){
                        temp.to=x; temp.w=z;
                        qm[y].push_back(temp);
                    }
                    //修改
                    cur =z;
                    if(sex[x]+sex[y]==1 )
                        ans = ans +(cur-ori);
                }
                else{
                    //询问八卦度:社交网络中所有异性好友之间的亲密度之和
                    printf("%lld
    ", ans );
                }
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    .NET重构(七):VS报表的制作
    【Linq】标准查询操作符
    1 TaskQueue 实现Task 队列
    1 疑惑处理
    1 JSONP
    1 Web 知识基础
    20 闭包
    1 基础知识
    Web 常用
    【Winform】2 Button
  • 原文地址:https://www.cnblogs.com/yspworld/p/4459575.html
Copyright © 2020-2023  润新知