2018-08-01 训练3

  • A  -- Pythagorean Theorem II

  • Description

In mathematics, the Pythagorean theorem — is a relation in Euclidean geometry among the three sides of a right-angled triangle. In terms of areas, it states:

In any right-angled triangle, the area of the square whose side is the hypotenuse (the side opposite the right angle) is equal to the sum of the areas of the squares whose sides are the two legs (the two sides that meet at a right angle).

The theorem can be written as an equation relating the lengths of the sides ab and c, often called the Pythagorean equation:

a2 + b2 = c2

where c represents the length of the hypotenuse, and a and b represent the lengths of the other two sides.

Given n, your task is to count how many right-angled triangles with side-lengths ab and c that satisfied an inequality 1 ≤ a ≤ b ≤ c ≤ n.

  • Input

The only line contains one integer n (1 ≤ n ≤ 104) as we mentioned above.

  • Output

Print a single integer — the answer to the problem.

  • Sample Input

74

  • Sample Output

35

扫描二维码关注公众号,回复: 2647633 查看本文章
  • 题目理解

就怕水题想太多,刚开始想要优化时间复杂度,所以做了一些准备工作却在这过程中遗忘最致命的(c>n时直接break因为在向下 循环是没有意义的事情),然后还有使用了ceil函数直接超时,int也是一样的效果但是却能过。还有预处理减少外循环次数时间反而因为运算耗费更多,所以要多做题积累经验,还有就是不要想太多不要想太多不要想太多,越简单越能过

#include<cstdio>
#include<cmath>
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        int ans=0;
        double maxn=n*1.0/sqrt(2)+1;
        for(int i=1;i<=maxn;++i){
            for(int j=i;j<=n;++j){
                double c=sqrt(i*i+j*j);
                if(c>n) break;
                //printf("%d %d %lf %lf\n",i,j,c,tmpc);
                if(c==(int)c){
                        ans++;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
#include<cstdio>
#include<cmath>
using namespace std;
int main()
{
    int n;
    scanf("%d",&n);
    int ans=0;
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            int c=i*i+j*j;
            if (c>n*n) break;
            double x=sqrt(c);
            if (abs((x-(int)x))<1e-8) ans++;
        }
    printf("%d\n",ans);
	return 0;
}
  • C -- 迷宫问题

  • Description

定义一个二维数组:

int maze[5][5] = {

       0, 1, 0, 0, 0,

       0, 1, 0, 1, 0,

       0, 0, 0, 0, 0,

       0, 1, 1, 1, 0,

       0, 0, 0, 1, 0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右

  • Input

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

  • Output

左上角到右下角的最短路径,格式如样例所示。

  • Sample Input

0 1 0 0 0

0 1 0 1 0

0 0 0 0 0

0 1 1 1 0

0 0 0 1 0

  • Sample Output

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

  • 题目理解

如果不输出路径这就是一个相当标准的bfs,所以只要在bfs过程中做一些标记就能输出路径,有以下两种方法

  1. 反向bfs遍历然后在每个格子上标记步数,这样在得到最短路的同时,由于只有唯一解,就会得到唯一从开头到结尾的有序序列然后在从头遍历的时候递减判断输出即可
  2. 在node结点开一个数组用来存下每次转移的i值,由于通过长度为4的二维数组转移状态如果记录下状态就可以直接在得到最短路的转移过程直接输出即可。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int a1[6][6];
int vis[6][6];
struct node
{
    int x;
    int y;
    int step;
    int num[50];
};
node ans;
int i,j,len;
int dis[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int x1=0;
int y1=0;
node  bfs()
{
    memset(vis,0,sizeof(vis));
    queue<node>q;
    node a,b;
    a.x=0;
    a.y=0;
    a.step=0;
    vis[0][0]=1;
    q.push(a);
    while(!q.empty())
    {
        a=q.front();
        q.pop();
        if(a.x==4&&a.y==4)
        {
           // len=a.step;
            //prinf(a);
            return a;
        }
        for(i=0;i<4;i++)
        {
            b=a;
            b.x=a.x+dis[i][0];
            b.y=a.y+dis[i][1];
            if(vis[b.x][b.y]||a1[b.x][b.y]==1)
                continue;
            if(b.x>=0&&b.x<5&&b.y>=0&&b.y<5)
            {
                 vis[b.x][b.y]=1;
                b.step=a.step+1;
                b.num[a.step]=i;
                q.push(b);

            }
        }
    }
    return a;
}
void prinf(node w)
{
    for(i=0;i<=w.step;i++)
    {

        printf("(%d, %d)\n",x1,y1);
        if(i!=w.step)
        {
            x1+=dis[w.num[i]][0];
            y1+=dis[w.num[i]][1];
        }
    }
}
int main()
{
    for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
        {
            scanf("%d",&a1[i][j]);
        }
    }
    ans=bfs();
    prinf(ans);
    return 0;
}
  • D -- Ideal Path

  • Description

New labyrinth attraction is open in New Lostland amusement park. The labyrinth consists of n rooms connected by m passages. Each passage is colored into some color ci . Visitors of the labyrinth are dropped from the helicopter to the room number 1 and their goal is to get to the labyrinth exit located in the room number n. Labyrinth owners are planning to run a contest tomorrow. Several runners will be dropped to the room number 1. They will run to the room number n writing down colors of passages as they run through them. The contestant with the shortest sequence of colors is the winner of the contest. If there are several contestants with the same sequence length, the one with the ideal path is the winner. The path is the ideal path if its color sequence is the lexicographically smallest among shortest paths. Andrew is preparing for the contest. He took a helicopter tour above New Lostland and made a picture of the labyrinth. Your task is to help him find the ideal path from the room number 1 to the room number n that would allow him to win the contest. Note: A sequence (a1, a2, . . . , ak) is lexicographically smaller than a sequence (b1, b2, . . . , bk) if there exists i such that ai < bi , and aj = bj for all j < i.

  • Input

The input file contains several test cases, each of them as described below. The first line of the input file contains integers n and m — the number of rooms and passages, respectively (2 ≤ n ≤ 100000, 1 ≤ m ≤ 200000). The following m lines describe passages, each passage is described with three integer numbers: ai , bi , and ci — the numbers of rooms it connects and its color (1 ≤ ai , bi ≤ n, 1 ≤ ci ≤ 109 ). Each passage can be passed in either direction. Two rooms can be connected with more than one passage, there can be a passage from a room to itself. It is guaranteed that it is possible to reach the room number n from the room number 1

  • Output

For each test case, the output must follow the description below. The first line of the output file must contain k — the length of the shortest path from the room number 1 to the room number n. The second line must contain k numbers — the colors of passages in the order they must be passed in the ideal path.

  • Sample Input

4 6

1 2 1

1 3 2

3 4 3

2 3 1

2 4 4

3 1 1

  • Sample Output

2

1 3

  • 题目理解

这道题其实和前面的bfs然后判断最短路径很像,但是在输出路线的过程中需要考虑最小字典序。我们知道当最短路可以通过图的层次遍历得到的时候bfs直接使用队列,但是优先队列并且非以0,1等递增的序列不能使用优先队列直接求,因为这里面可能循环其他情况多遍才能得到正确答案,要么是超时要么是答案错误。首先使用反向bfs得到最短路,然后正向bfs的时候我们可以看做一层一层的得出最优解,将每一层的所有节点出队列然后选取最优值,这样就不会出现像网上的代码出现的问题。这里是参考网上代码但是自己优化后写的。这里要记得使用vis,inqueue维护剔除重边和平行路径的时间复杂度以免超时。这里由于结点太多,邻接数组开不了所以使用邻接表存图

#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int maxn=1e6+5;
const int inf=0x7fffffff;
struct ver{
  int v,c;
  ver(int V,int C):v(V),c(C){}
};
int d[maxn],vis[maxn],inqueue[maxn],res[maxn],pre[maxn];
vector<ver> edge[maxn];
int n,m;
void bfs(int start,int finish){
    memset(vis,0,sizeof(vis));
    memset(inqueue,0,sizeof(inqueue));
    int u,v;
    queue<int> q;
    q.push(start);
    if(start==1){
     for(int i=0;i<maxn;++i) res[i]=inf;
     while(!q.empty()){
       int cnt=0;
       while(!q.empty()){
         u=q.front();pre[cnt++]=u;q.pop();vis[u]=1;
         if(u==finish) return ;
       }
       int minc=inf;
       for(int i=0;i<cnt;++i){
         u=pre[i];
         for(int i=0,len=edge[u].size();i<len;++i){
            v=edge[u][i].v;
            if(d[u]==d[v]+1&&!vis[v])//来自下一个点
                minc=min(minc,edge[u][i].c);
         }
       }
       for(int i=0;i<cnt;++i){
         u=pre[i];
         for(int i=0,len=edge[u].size();i<len;++i){
            v=edge[u][i].v;
            if(d[u]==d[v]+1&&minc==edge[u][i].c&&!inqueue[v]&&!vis[v])
               q.push(v),inqueue[v]=1;
         }
       }
       int pos=d[start]-d[u];
       res[pos]=min(res[pos],minc);
     }
    }else{
       while(!q.empty()){
         u=q.front();
         q.pop();
         vis[u]=1;
         for(int i=0,len=edge[u].size();i<len;++i){
            if(!vis[v=edge[u][i].v]&&!inqueue[v]){
                d[v]=d[u]+1;
                if(v==start) return ;
                q.push(v);
                inqueue[v]=1;
            }
         }
       }
    }
}
int main(){
   while(scanf("%d%d",&n,&m)!=EOF){
      for(int i=1;i<=n;++i)edge[i].clear();
      memset(d,-1,sizeof(d));//如果初始化为0最后如果d[1]为1那么默认1到所有结点地位相同这时候会出错
      d[n]=0;
      int a,b,c;
      while(m--){
        scanf("%d%d%d",&a,&b,&c);
        if(a!=b){
          edge[a].push_back(ver(b,c));
          edge[b].push_back(ver(a,c));
        }
      }
      bfs(n,1);
      bfs(1,n);
      printf("%d\n",d[1]);
      for(int i=0;i<d[1];++i){
        if(i) printf(" ");
        printf("%d",res[i]);
      }printf("\n");
   }
   return 0;
}
  • E  -- Key Task

  • Description

The Czech Technical University is rather old — you already know that it celebrates 300 years of its existence in 2007. Some of the university buildings are old as well. And the navigation in old buildings can sometimes be a little bit tricky, because of strange long corridors that fork and join at absolutely unexpected places. 
The result is that some first-graders have often di?culties finding the right way to their classes. Therefore, the Student Union has developed a computer game to help the students to practice their orientation skills. The goal of the game is to find the way out of a labyrinth. Your task is to write a verification software that solves this game. 
The labyrinth is a 2-dimensional grid of squares, each square is either free or filled with a wall. Some of the free squares may contain doors or keys. There are four di?erent types of keys and doors: blue, yellow, red, and green. Each key can open only doors of the same color. 
You can move between adjacent free squares vertically or horizontally, diagonal movement is not allowed. You may not go across walls and you cannot leave the labyrinth area. If a square contains a door, you may go there only if you have stepped on a square with an appropriate key before.

  • Input

The input consists of several maps. Each map begins with a line containing two integer numbers R and C (1 ≤ R, C ≤ 100) specifying the map size. Then there are R lines each containing C characters. Each character is one of the following: 

Note that it is allowed to have 

  • more than one exit,
  • no exit at all,
  • more doors and/or keys of the same color, and
  • keys without corresponding doors and vice versa.
  • You may assume that the marker of your position (“*”) will appear exactly once in every map. 

    There is one blank line after each map. The input is terminated by two zeros in place of the map size.
  • Output

For each map, print one line containing the sentence “Escape possible in S steps.”, where S is the smallest possible number of step to reach any of the exits. If no exit can be reached, output the string “The poor student is trapped!” instead. 
One step is defined as a movement between two adjacent cells. Grabbing a key or unlocking a door does not count as a step.

  • Sample Input

1 10

*........X

1 3

*#X

3 20

####################                                                                                                                                   #XY.gBr.*.Rb.G.GG.y#                                                                                                                                       ####################

0 0

  • Sample Output

Escape possible in 9 steps.

The poor student is trapped!

Escape possible in 45 steps.

  • 题目理解

这道题和之前做过的练习题简直相差无几,我们开两个长度为4的一维数组就可以将门和钥匙完美映射到1-4,这样就可以直接使用不超过15的数将钥匙的状态存下来。由于可能一个结点会由于钥匙有或者没有的原因来回遍历所以以为的vis不能正确的判断是否能够入队列/访问,所以需要纪录n*m*16 种状态判断该种情况是否经历不在重新入队列,队列空时找不到解就无法逃脱,其他情况一定能够得到最优情况

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
const int maxn=105;
using namespace std;
int n,m,s,t;
int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
char g[maxn][maxn];
int vis[maxn][maxn][17];
char door[4]={'B','Y','R','G'};
char open[4]={'b','y','r','g'};
struct node
{
    int step,x,y,key;
};
int bfs()
{
    queue<node>q;
    node now,next;
    now.x=s;now.y=t;now.step=now.key=0;
    vis[s][t][0]=1;
    q.push(now);
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        if(g[now.x][now.y]=='X')return now.step;
        for(int i=0;i<4;i++)
        {
            next.x=now.x+dir[i][0];
            next.y=now.y+dir[i][1];
            next.step=now.step+1;
            next.key=now.key;
            if(next.x<1||next.x>n||next.y<1||next.y>m||g[next.x][next.y]=='#')continue;
            if(g[next.x][next.y]>='A'&&g[next.x][next.y]<='Z'&&g[next.x][next.y]!='X')
            {
                for(int j=0;j<4;j++)
                    if(g[next.x][next.y]==door[j])
                    {
                        if(next.key&(1<<j)&&!vis[next.x][next.y][next.key])
                        {
                            vis[next.x][next.y][next.key]=1;
                            q.push(next);
                        }
                        break;
                    }
            }
            else if(g[next.x][next.y]>='a'&&g[next.x][next.y]<='z')
            {
                for(int j=0;j<4;j++)
                    if(g[next.x][next.y]==open[j])
                    {
                        if((next.key&(1<<j))==0)
                            next.key+=(1<<j);
                        if(!vis[next.x][next.y][next.key])
                        {
                            vis[next.x][next.y][next.key]=1;
                            q.push(next);
                        }
                    }
            }
            else
            {
                if(!vis[next.x][next.y][next.key])
                {
                    vis[next.x][next.y][next.key]=1;
                    q.push(next);
                }
            }
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d",&n,&m),n|m)
    {
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            scanf("%s",g[i]+1);
            for(int j=1;j<=m;j++)
                if(g[i][j]=='*'){s=i;t=j;}
        }
        int ans=bfs();
        if(ans==-1)printf("The poor student is trapped!\n");
        else printf("Escape possible in %d steps.\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zm_zsy/article/details/81349224