• Codeforces Round #131 (Div. 2)


    模拟一场,这场题目算是比较巧的.

    a. 很简单的暴力题

    b. 有点麻烦的题, 用一堆数字拼成一个最大的能被2,3,5 同时整除的数, 首先必须最后一位数字必须是0, 然后数字的总和要能被三整除 。 

    解法是枚举一个到两个数字,看减少这些数字能不能使数字的总和被3整除。 如果没有就输出-1

    #include <stdio.h>
    #include <string.h>
    #include <string>
    #include <iostream>
    using namespace std;
    
    int mark[10];
    
    int main()
    {
        int n;
        scanf("%d",&n);
        int sum=0;
        for(int i=0;i<n;i++)
        {
            int tmp;
            scanf("%d",&tmp);
            sum+=tmp;
            mark[tmp]++;
        }
        if(mark[0]==0)
        {
            printf("-1");
        }
        else
        {
            if(sum%3==0)
            {
                int flag=0;
                for(int i=9;i>0;i--)
                {
                    for(int j=mark[i];j>0;j--)
                    {
                        flag=1;
                        printf("%d",i);
                    }
                }
                if(flag==0) printf("0");
                else 
                {
                    for(int i=0;i<mark[0];i++)
                        printf("0");
                }
                return 0;
            }
            int sign=0;
            for(int i=1;i<=9;i++)
            {
                if(mark[i]!=0)
                {
                    mark[i]--;
                    if((sum-i)%3==0)
                    {
                        sign=1;
                        break;
                    }
                    mark[i]++;
                }
            }
            if(sign==1)
            {
                int flag=0;
                for(int i=9;i>0;i--)
                {
                    for(int j=mark[i];j>0;j--)
                    {
                        flag=1;
                        printf("%d",i);
                    }
                }
                if(flag==0) printf("0");
                else 
                {
                    for(int i=0;i<mark[0];i++)
                        printf("0");
                }
                return 0;
            }
            for(int i=1;i<=9;i++)
            {
                if(mark[i]==0) continue;
                mark[i]--;
                for(int j=1;j<=9;j++)
                {
                    if(mark[j]!=0)
                    {
                        mark[j]--;
                        if((sum-i-j)%3==0)
                        {
                            sign=1;
                            break;
                        }
                        mark[j]++;
                    }
                }
                if(sign==1)
                    break;
                mark[i]++;
            }
            if(sign==1)
            {
                int flag=0;
                for(int i=9;i>0;i--)
                {
                    for(int j=mark[i];j>0;j--)
                    {
                        flag=1;
                        printf("%d",i);
                    }
                }
                if(flag==0) printf("0");
                else 
                {
                    for(int i=0;i<mark[0];i++)
                        printf("0");
                }
                return 0;
            }
            else
                printf("-1");
        }
        return 0;
    }

    3. 第三题很是巧妙, 也很值得一学。  

    题目的关键在于,边的权值 。 1->2 ,2->3 ,3->1 的权都是1,而 2->1, 3->2, 1->3 的权都为2. 由这个特殊的性质,就可以发现沿着1->2->3->1的路线走始终是最小的 因为假设你在1 你要去3 , 你可以选择1->2->3 也可以1-> 3 这两种路线花费是相同的. 而如果要去2的话1->2 就比2->1 花费要小.

    所以问题就变得很简单了.

    #include <stdio.h>
    #include <string>
    #include <string.h>
    #include <iostream>
    using namespace std;
    #define N 220
    struct node
    {
        int to,next,w;
    }edge[N*N];
    
    int n;
    int cnt,pre[N];
    int mark[N],sign[N];
    int in[N];
    int save[N];
    int mi;
    int sum;
    void add_edge(int u,int v,int w)
    {
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=pre[u];
        pre[u]=cnt++;
    }
    
    void dfs(int s,int k)
    {
    
        for(int ii=0;ii<n;ii++) // 进行n次
        for(int i=1;i<=n;i++)
        {
            if(sign[i]==0&&mark[i]==s&&in[i]==0)
            {
                k++; // 把这个电脑能打的都打完
                sign[i]=1;
                for(int p=pre[i];p!=-1;p=edge[p].next)
                    if(sign[edge[p].to]==0) in[edge[p].to]--;
            }
        }
        if(k==n) return ;
        sum++;
        if(s==3) s=1;
        else s++;
        dfs(s,k);
    }
    
    int main()
    {
        cnt=0;
        memset(pre,-1,sizeof(pre));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&mark[i]);
        }
        for(int i=1;i<=n;i++)
        {
            int tmp;
            scanf("%d",&tmp);
            for(int j=0;j<tmp;j++)
            {
                int to;
                scanf("%d",&to);
                add_edge(to,i,1);
                save[i]++;
            }
        }
        mi=9999999;
        for(int i=1;i<=3;i++)
        {
            sum=0;
            memset(sign,0,sizeof(sign));
            for(int j=1;j<=n;j++)
            {
                in[j]=save[j];
            }
            dfs(i,0);
            if(sum<mi) mi=sum;
        }
        printf("%d",mi+n);
        return 0;
    }
  • 相关阅读:
    [转载]解析.Net框架下的XML编程技术
    Intercept and Manage Windows Originated by Thirdparty Components Hosted in C# Application
    [创业]<高效能人士的七个习惯>有感
    [关于DES程序]对前DES1.0源码bug的修正
    The secret benefit of search engine optimisation: Increased usability
    效率不高的7个原因
    [PDF]Intrusion Detection Techniques and Approaches
    [转载]基于数据挖掘的入侵检测系统
    [转载]在 C# 中加载自己编写的动态链接库
    [转载]在WinForm中使用Web Services 来实现 软件 自动升级( Auto Update ) (C#)
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/2915766.html
Copyright © 2020-2023  润新知