zoukankan      html  css  js  c++  java
  • [ Google APAC 2015 University Graduates Test ] Round C APAC Test

    题目链接:

    http://code.google.com/codejam/contest/5214486/dashboard


    Problem A. Minesweeper

    题目意思:

    扫雷。告诉地雷所在的位置,求至少须要几步,把全部的非雷位置都翻过来。假设某一个格子周围都不是地雷。则翻转该格子会把周围的格子都翻转过来。

    解题思路:

    dfs找连通块

    先把非雷格子周围的地雷总数求出,然后对于周围没有地雷的格子找连通块。剩下的每一个格子都须要再翻转一次。

    代码:

    //#include<CSpreadSheet.h>
    
    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<sstream>
    #include<cstdlib>
    #include<string>
    #include<string.h>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<stack>
    #include<list>
    #include<queue>
    #include<ctime>
    #include<bitset>
    #include<cmath>
    #define eps 1e-6
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define ll __int64
    #define LL long long
    #define lson l,m,(rt<<1)
    #define rson m+1,r,(rt<<1)|1
    #define M 1000000007
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    using namespace std;
    
    #define Maxn 330
    
    char sa[Maxn][Maxn];
    int nu[Maxn][Maxn];
    bool vis[Maxn][Maxn];
    int n,ans;
    int dir[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
    
    bool iscan(int x,int y)
    {
        if(x<1||x>n||y<1||y>n)
            return false;
        return true;
    }
    
    void dfs(int x,int y)
    {
        for(int i=0;i<8;i++)
        {
            int xx=x+dir[i][0],yy=y+dir[i][1];
            if(!iscan(xx,yy)||vis[xx][yy])
                continue;
            ans++;
            vis[xx][yy]=true;
            if(!nu[xx][yy])
                dfs(xx,yy);
        }
    }
    int main()
    {
        freopen("A-large.in","r",stdin);
       freopen("A-large.out","w",stdout);
       int t,cas=0;
    
       scanf("%d",&t);
       while(t--)
       {
           scanf("%d",&n);
           int cnt=0;
    
           for(int i=1;i<=n;i++)
           {
               scanf("%s",sa[i]+1);
               for(int j=1;j<=n;j++)
                    if(sa[i][j]=='.')
                        cnt++;
           }
           memset(nu,0,sizeof(nu));
           for(int i=1;i<=n;i++)
           {
               for(int j=1;j<=n;j++)
               {
                   if(sa[i][j]=='.')
                        continue;
                   for(int k=0;k<8;k++)
                   {
                       int x=i+dir[k][0],y=j+dir[k][1];
                       if(!iscan(x,y)||sa[x][y]=='*')
                            continue;
                       nu[x][y]++;
                   }
               }
           }
           memset(vis,false,sizeof(vis));
           ans=0;
           int temp=0;
           for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
               {
                   if(sa[i][j]=='*')
                        continue;
                   if(!nu[i][j]&&!vis[i][j])
                   {
                       vis[i][j]=true;
                       temp++;
                       ans++;
                       dfs(i,j);
                   }
               }
          //printf("ans:%d cnt:%d
    ",ans,cnt);
          printf("Case #%d: %d
    ",++cas,cnt-ans+temp);
    
       }
        return 0;
    }
    
    


    Problem B. Taking Metro

    题目意思:

    有n号地铁线,每号地铁线有Sni个站,告诉地铁经过每号线相邻两站的花费时间。有m个换乘点,每一个换乘点连接两个不同的地铁线路两站,告诉每一个换乘点的花费时间。当到达某号线的某个网站时,假设要乘该号线,须要等待该号线所需时间。

    解题思路:

    BFS【最短路】

    此题难点就是假设恰好要乘某号线时,要等待该号线的时间。不优点理。

    把每一个站看成点,把点翻倍,如果总共同拥有li个点。

    A点表示已经在乘该站所在的那号线喽,等待时间已经计算好了。A+li表示刚到该站,还没等该号线所需等待时间。要分开处理,不然不好转移。从li+A到A须要花费等待的时间,从A到li+A则不须要。

    对于换乘点。要么刚乘车到A,换成到B+li.要么从li+A换乘到li+B.

    注意全部的边都是双向的。

    最后求出li+s到li+e就可以。

    代码:

    //#include<CSpreadSheet.h>
    
    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<sstream>
    #include<cstdlib>
    #include<string>
    #include<string.h>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<stack>
    #include<list>
    #include<queue>
    #include<ctime>
    #include<bitset>
    #include<cmath>
    #define eps 1e-6
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define ll __int64
    #define LL long long
    #define lson l,m,(rt<<1)
    #define rson m+1,r,(rt<<1)|1
    #define M 1000000007
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    using namespace std;
    
    #define Maxn 210000
    struct Edge
    {
        int to,add,ti;
    
        Edge(int a,int b,int c)
        {
            to=a,ti=b,add=c;
        }
    };
    vector<vector<Edge> >myv;
    int sum[110],cn[110],ct[110],n,m,q;
    bool vis[Maxn];
    
    struct Node
    {
        int hav,id,wai;
    
        Node(){}
        Node(int a,int b,int c)
        {
            hav=a,id=b,wai=c;
        }
        friend bool operator <(Node a,Node b)
        {
            return a.hav>b.hav;
        }
    };
    
    int bfs(int s,int e)
    {
        priority_queue<Node>myq;
        myq.push(Node(0,s,-1));
    
        while(!myq.empty())
        {
            Node now=myq.top();
            //printf("id:%d hav:%d
    ",now.id,now.hav);
            //system("pause");
            if(now.id==e)
                return now.hav;
            myq.pop();
            if(vis[now.id])
                continue;
            vis[now.id]=true;
    
            for(int i=0;i<myv[now.id].size();i++)
            {
                int ne=myv[now.id][i].to;
                Node nex;
                if(vis[ne])
                    continue;
                nex.hav=now.hav+myv[now.id][i].ti;
                nex.id=ne;
                myq.push(nex);
            }
        }
        return -1;
    
    }
    
    int main()
    {
       //freopen("B-large-practice.in","r",stdin);
       //freopen("B-large-practice.out","w",stdout);
       int t,cas=0;
    
       scanf("%d",&t);
       while(t--)
       {
           int n;
           scanf("%d",&n);
           memset(sum,0,sizeof(sum));
           myv.clear();
           myv.resize(n*2050);
    
           for(int i=1;i<=n;i++)
           {
               scanf("%d%d",&cn[i],&ct[i]);
               for(int j=1;j<cn[i];j++)
               {
                   int ti;
                   scanf("%d",&ti);
                   int a=sum[i-1]+j,b=sum[i-1]+j+1;
                   myv[a].push_back(Edge(b,ti,i));
                   myv[b].push_back(Edge(a,ti,i));
               }
               sum[i]=sum[i-1]+cn[i];
           }
           int li=sum[n];
           for(int i=1;i<=n;i++)
           {
               int a=sum[i-1],b=sum[i];
    
               for(int j=a+1;j<=b;j++)
               {
                   myv[li+j].push_back(Edge(j,ct[i],-1));
                   myv[j].push_back(Edge(li+j,0,-1));
               }
           }
           scanf("%d",&m);
           for(int i=1;i<=m;i++)
           {
               int a1,b1,a2,b2,c;
               scanf("%d%d%d%d%d",&a1,&b1,&a2,&b2,&c);
               myv[li+sum[a1-1]+b1].push_back(Edge(li+sum[a2-1]+b2,c,-1));
               myv[sum[a1-1]+b1].push_back(Edge(li+sum[a2-1]+b2,c,-1));
               myv[li+sum[a2-1]+b2].push_back(Edge(li+sum[a1-1]+b1,c,-1));
               myv[sum[a2-1]+b2].push_back(Edge(li+sum[a1-1]+b1,c,-1));
           }
           scanf("%d",&q);
           printf("Case #%d:
    ",++cas);
    
           for(int i=1;i<=q;i++)
           {
               int a1,b1,a2,b2;
               scanf("%d%d%d%d",&a1,&b1,&a2,&b2);
               memset(vis,false,sizeof(vis));
               int temp1=bfs(li+sum[a1-1]+b1,li+sum[a2-1]+b2);
               //memset(vis,false,sizeof(vis));
               //int temp2=bfs(sum[a2-1]+b2,sum[a1-1]+b1);
               printf("%d
    ",temp1);//min(temp1,temp2));
           }
    
       }
        return 0;
    }
    /*
    10
    2
    3 5
    3 4
    3 6
    1 2
    2
    1 2 2 2 9
    2 2 1 2 8
    1
    1 1 2 3
    24
    */
    
    


    Problem C. Broken Calculator

    题目意思:

    一个坏的计算器有些数字button不能用。运算符仅仅能用*和=,给定一个数x,求得到x所需的最少的按键步数。否则直接输出-1.

    解题思路:

    记忆话搜索

    由于仅仅有一个乘运算,所以枚举n的约数i,假设得到i的最少次数没有计算。则先计算得到i的最少次数,方式和计算n是一样的。

    再以相同方式计算n/i,然后更新n的最少次数min(nu[i]+nu[n/i]+1),+1表示乘号。

    代码:

    //#include<CSpreadSheet.h>
    
    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<sstream>
    #include<cstdlib>
    #include<string>
    #include<string.h>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<stack>
    #include<list>
    #include<queue>
    #include<ctime>
    #include<bitset>
    #include<cmath>
    #define eps 1e-6
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define ll __int64
    #define LL long long
    #define lson l,m,(rt<<1)
    #define rson m+1,r,(rt<<1)|1
    #define M 1000000007
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    using namespace std;
    
    #define Maxn 1100000
    int nu[Maxn];
    int hav[12];
    
    int iscan(int x)
    {
        int res=0;
        while(x)
        {
            if(!hav[x%10])
                return -1;
            x/=10;
            res++;
        }
        return res;
    }
    
    int dfs(int cur)
    {
        if(nu[cur]!=-1)
            return nu[cur];
        int temp=iscan(cur);
        if(temp!=-1)
            nu[cur]=temp;
        else
            nu[cur]=INF;
    
        for(int i=1;i*i<=cur;i++)
        {
            if(cur%i==0)
            {
                int t1=dfs(i);
                int t2=dfs(cur/i);
                nu[cur]=min(nu[cur],t1+t2+1);
            }
        }
        return nu[cur];
    }
    int main()
    {
        freopen("C-large-practice.in","r",stdin);
      freopen("C-large-practice.out","w",stdout);
       int t,cas=0,n;
    
       scanf("%d",&t);
       while(t--)
       {
           for(int i=0;i<10;i++)
                scanf("%d",&hav[i]);
           scanf("%d",&n);
           memset(nu,-1,sizeof(nu));
    
           nu[n]=dfs(n);
           if(nu[n]==INF)
                printf("Case #%d: Impossible
    ",++cas);
           else
                printf("Case #%d: %d
    ",++cas,nu[n]+1);
    
       }
        return 0;
    }
    



  • 相关阅读:
    学习JavaDay07
    学习JavaDay05
    学习JavaDay0402
    学习JavaDay04
    学习JavaDay03
    学习JavaDay02
    学习JavaDay01
    数据库的增删改查
    关于Spring
    关于多线程Thread的简单应用
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7275734.html
Copyright © 2011-2022 走看看