Codeforces Round #325 (Div. 2) (586A,586B,585A,585B)

来源:互联网 发布:光纤分布数据接口fddi 编辑:程序博客网 时间:2024/06/05 06:21

1.Alena's Schedule


题目链接:

http://codeforces.com/problemset/problem/586/A

解题思路:

To solve this problem one should remove all leading and trailing zeroes from array and then calculate the number of ones and 

number of zeroes neighboured by ones. The sum of this values is the answer for the problem.

Complexity: O(n).

题目大意:

一天有n个课时,但是,不是每个课时都有课,(1表示该课时有课,0表示该课时没课)。因为Alena家离学校比较远,所以如果这节有

直到下一节有课之间只有小于等于一个(没课的)课时,那么Alena就留在学校等待下一节课,否则就回家,求Alena在学校的时

(每个课时按1来算)

AC代码:

#include <iostream>#include <cstdio>using namespace std;int a[110];int main(){    int n;    while(~scanf("%d",&n)){        int sum = 0;        for(int i = 0; i < n; i++)            scanf("%d",&a[i]);        int i = 0;        while(a[i] == 0 && i < n)            i++;        int j = n-1;        while(a[j] == 0 && j > 0)            j--;        for(; i < j;){            if(a[i] == 0 && a[i+1] == 0){                while(i < j && a[i] == 0)                    i++;            }            else{                a[i] = 1;                i++;            }        }        for(int i = 0; i < n; i++)            sum += a[i];        printf("%d\n",sum);    }    return 0;}

2.Laurenty and Shop


题目链接:

http://codeforces.com/problemset/problem/586/B

解题思路:

Let's call some path ith if we start it by going i times left, then we cross the prospect and go left n - 1 - i times again. Let di be equal to the time we should wait on traffic lights while following i-th path. If we consider any way from the shop to home, it is equal (but reversed) to only path from home to the shop, meaning that we need to find two distinct paths from home to the shop. So the answer to the problem is the sum of the smallest and the second smallest values among di. One could easily calculate di using calculated di - 1, so di could be found in one for cycle.

If we will consider only two minimum values among di, solution complexity will be O(n).

Complexity: O(n).

题目大意:

就和例图的一样,从下面的第n个位置去到上面的第一个位置,然后再从上面的第一个位置回到下面的第n个位置,要求在来回两次

的路径不能完全一样,并且中间的过道只能走一次,求最短的来回值。

算法思想:

如果中间的过道没限制可能麻烦一点,但是因为题目限制了中间的过道只能走一遍,所以就暴力找从上面到下面在哪个位置走过道

就行了,然后再取两个最小的路径相加即可

AC代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int a[110],b[110],c[110];int dis[110];int main(){    int n;    while(~scanf("%d",&n)){        a[0] = 0;c[0] = 0;        for(int i = 1; i < n; i++)            scanf("%d",&a[i]);        for(int i = 1; i < n; i++)            scanf("%d",&c[i]);        for(int i = 0; i < n; i++)            scanf("%d",&b[i]);        int sum = 0;        for(int i = 0; i < n; i++){            sum += a[i];            dis[i] = sum+b[i];            //cout<<dis[i]<<endl;            for(int j = i+1; j < n; j++)                dis[i] += c[j];            //cout<<dis[i]<<endl<<endl;        }        sort(dis,dis+n);        printf("%d\n",dis[0]+dis[1]);    }    return 0;}


3.Gennady the Dentist


题目链接:

http://codeforces.com/problemset/problem/585/A

解题思路:

Let's store for each child his current confidence value and a boolean indicating whether child had left the queue (or visited the dentist office) or not. Then one could easily process children one by one, considering only children who still are in the queue (using boolean array), and changing stored values.

Such solution has complexity O(n2) and requires author's attention much, especially the case with possible confidence value overflowing. Of course there are much faster solutions not required in our case.

题目大意:

一群小孩排成一列去看牙医,每个小孩有个忍耐度p,当小孩看牙的时候的哭喊声音大小v,当小孩离开的时候哭喊的声音大小d。当

一个小屁孩去看牙医的时候,会哭喊,然后队头的小屁孩就受到v点伤害(忍耐度下降v),第二个受到v-1点,以此类推直到没有伤

害了。这之后,会出现一些忍耐度<0的小屁孩,这些小孩会以d的声音哭,然后离开,这个过程会导致排在这个小屁孩后面的小屁

孩都受到d点伤害。问:最后能看牙医的小孩的顺序

算法思想:

模拟即可,注意:会爆int,要用long long 。

AC代码:

#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;typedef long long ll;struct node{    ll v,d,p;}no[4005];vector<int> v;int main(){    int n;    while(~scanf("%d",&n)){        v.clear();        for(int i = 1; i <= n; i++)            scanf("%lld%lld%lld",&no[i].v,&no[i].d,&no[i].p);        for(int i = 1; i <= n; i++){            if(no[i].p >= 0){                v.push_back(i);                ll sum1 = no[i].v,sum2 = 0;//sum1: vi,sum2:dj.                for(int j = i+1; j <= n; j++){                    if(no[j].p >= 0){                        no[j].p -= (sum1+sum2);                        sum1 = max(0LL,sum1-1);                        if(no[j].p < 0)                            sum2 += no[j].d;                    }                }            }        }        int l = v.size();        printf("%d\n",l);        for(int i = 0; i < l-1; i++)            printf("%d ",v[i]);        printf("%d\n",v[l-1]);    }    return 0;}

4.Phillip and Trains

题目链接:

http://codeforces.com/problemset/problem/585/B

解题思路:

One could consider a graph with vertices corresponding to every (x, y) position. I should notice that train positions for each Phillip position are fully restorable from his y coordinate. Edge between vertices u and v means that we could get from position corresponding to u to position corresponding by v in one turn without moving onto a train cell or moving in a cell which will be occupied by some train before the next turn. All we need next is to find whether any finishing position is reachable from the only starting position (using BFS or DFS, or, as soon as graph is a DAG, dynamic programming).

As soon as graph has O(n) vertices and O(n) edges, solution complexity equals to O(n).

题目大意:

有一个人从左往右前进,每次先往左走一格,然后可以往上或者往下走或者就不动,走的过程中会有火车跑过来,每次火车都会走

两格。规定是人先走一次,然后所有火车再走一次。问能不能不被火车撞到并且到达最右边。

算法思想:

bfs,根据相对运动,每一次火车运动时,相当于火车不动,人往右前进两格。

注意:如果往右走一步已经不能成功,那么这种情况肯定行不通。

AC代码:

#include <iostream>#include <cstdio>#include <cstring>#include <cctype>#include <queue>using namespace std;typedef pair<int,int> P;char str[5][110];int vis[5][110];int st,n,k;bool bfs(int st){    queue<P> q;    q.push(P{st,1});    while(!q.empty()){        int x = q.front().first,y = q.front().second;        q.pop();        if(isalpha(str[x][++y]))            continue;        if(y >= n)            return true;        for(int i = -1; i <= 1; i++){            int xx = x+i;            if(xx < 1 || xx > 3)                continue;            if(isalpha(str[xx][y]) || isalpha(str[xx][y + 1]) || isalpha(str[xx][y + 2]) || vis[xx][y + 2] == 1)                continue;            int yy = y+2;//相对运动            if(yy >= n)                return true;            vis[xx][yy] = 1;            q.push(P{xx,yy});        }    }    return false;}int main(){    int T;    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&k);        memset(vis,0,sizeof(vis));        for(int i = 1; i <= 3; i++){            scanf("%s",str[i]+1);            if(str[i][1] == 's')                st = i;        }        if(bfs(st))            printf("YES\n");        else            printf("NO\n");    }    return 0;}


0 0
原创粉丝点击