2018 ACM-ICPC, Syrian Collegiate Programming Contest

这是2018年叙利亚大学程序设计赛,星期一没什么比赛就拿这套题目练了一下手,在这里写几道我做出来的里面还算有点难度的题目(实力有限好多题看都没看)

比赛链接 http://codeforces.com/gym/102006

H. Bugged System

Problem Description

Mr. Light is visiting a city with a “smart” metro system. Or so it seems …

There are exactly n stations in a line, where the ith station is located at a distance xi from the beginning of the line. You can check into some station, travel between the stations as many times as you want in both directions, and check out from another station. The metro card will track the sum of distances you traveled and charge you accordingly once you check out of your destination station.
However, there seems to be a bug in the system; if you happen to check in and out from the same station, you will be charged 0 credit. This creates the possibility of a scenario where one person traveling from stations a to b, and another person traveling from stations b to a, they can now meet up at some station and swap their cards. Therefore when they arrive, they both will pay 0 credit. Check the explanation of the first sample test for another scenario.
A person can go to any number of stations and wait as long as they like. Two people that meet at the same station can swap their cards.
You are given the starting and destination stations for m people traveling along the metro. Is it possible for all m people to check out from their destination stations and pay 0 credit? If so, print the minimum total distance they must travel to achieve this.

Input

The first line of input contains a single integer T (1 ≤ T ≤ 3700), the number of test cases.
The first line of each test case contains two space-separated integers n and m (2 ≤ n, m ≤ 2 × 105), the number of stations and the number of people that will be using the metro stations.
The second line contains n space-separated integers x1, x2, …, xn (0 ≤ xi ≤ 2 × 106), where xi is the distance of the ith station from the beginning of the line.
Each of the following m lines contains two integers si and di (1 ≤ si, di ≤ n, si ≠ di), representing the starting and destination stations of ith person.
The sum of n over all test cases doesn’t exceed 2 × 106, the same is true for m.

Output

For each test case, output on a single line with the minimum total distance all m people need to travel to pay 0 credit.
If it is not possible, output  - 1 on a line.

Example input

2
3 3
10 50 25
1 2
2 3
3 1
4 2
1 10 5 3
1 2
4 3

Example output

80
-1

题目的意思呢我也是拿我70分的英语加上谷歌翻译才看懂的,大概就是有一个bugged的交通管理系统,如果一个人从出发点出发到达目标点,如果在目标点和另一个人交换公交卡然后出站系统就会自动认为他没有动就会收取0元,题目给出了各个公交站离初始点的距离和多个人的数据也给出了每个人的出发和目标点,问你能不能所有人都收取0元,能则输出所有人最少要坐多远的车,不能则输出-1。

思路

这道题目仔细想一想如果要所有人都收取0元,则必须要所有站点的“出度”和“入度”相等,这样才可以让所有人刚好可以交换到自己目标点出发的公交卡,另外要求总距离最小,其实就是每个人直接从出发点到目标点和目标点的人交换后目标点的人再重复操作,最后肯定会形成一个“环”,即可求出最小总路程。

代码
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
__int64 start[200005],enda[200005],juli[200005];
int main()
{
	__int64 n,i,j,k,a,b,s,e;
 
freopen("bugged.in","r",stdin);
 
	scanf("%I64d",&n);
 
	for(i=0;i<n;i++)
	{
		scanf("%I64d%I64d",&a,&b);
		memset(start,0,sizeof(start));
		memset(enda,0,sizeof(enda));
		memset(juli,0,sizeof(juli));
		k=0;
		for(j=1;j<=a;j++)
			scanf("%I64d",&juli[j]);
		for(j=0;j<b;j++)
		{
			scanf("%I64d%I64d",&s,&e);
			k=k+abs(juli[e]-juli[s]);
			start[s]++;
			enda[e]++;
		}
		for(j=1;j<=a;j++)
		{
			if(start[j]!=enda[j])
				break;
		}
		if(j!=a+1)
			printf("-1");
		else
		{
			printf("%I64d",k);
		}
		if(i!=n-1)
			printf("\n");
	}
	return 0;
	/*其实这道题目不难,思路也很好找,但是还是浪费了我很久的时间,主要是题目的数据边界没有考虑清楚再加上那个memset一开始觉得会不会很浪费时间就用for循环来赋0,结果用j来循环最后却用i来赋值,近视眼表示看了好久都没看出来,哭了哭了.*/
}

C. Portals

Problem Description

Mr. Light is making a video game that can be represented as a ninja moving around a grid of 1 row and n columns.
Each cell is one of 5 types:

  1. ‘.’; an empty cell. A ninja in this cell can move to the cell directly to its left or its right (if it exists and it is not blocked).
  2. ‘#’; a blocked cell. A ninja cannot enter this cell.
  3. ‘o’; a portal. A ninja in this cell can jump to any other cell of the same type, or to the cell directly to its left or its right (if it exists and it is not blocked).
  4. ‘s’; starting cell of the ninja. There is exactly one cell of this type in the grid.
  5. ‘e’; ending cell of the ninja. There is exactly one cell of this type in the grid.

The starting and ending cells are also empty cells, so the ninja can move from and to them in the same way.
Mr. Light wants to change a minimum number of empty cells to blocked cells (type 1 to type 2) such that there is no possible way for the ninja to get from the starting cell to the ending cell. Cells of type 2, 3, 4, and 5 cannot be changed.

Input

The first line of input contains a single integer T (1 ≤ T ≤ 27000), the number of test cases.
The first of each test case is n (2 ≤ n ≤ 2 × 105), the number of columns in the grid.
The next line contains n characters, where each character is one of the following: ‘.’, ‘#’, ‘o’, ‘s’, or ‘e’. It is guaranteed that there is exactly one ‘s’ and one ‘e’ in the grid.
The sum of n over all test cases doesn’t exceed 2 × 106.

Output

For each test case, output the minimum number of empty cells that need to be blocked to make it impossible for the ninja to reach the ending cell. If there’s no way to achieve that, print  - 1, on a single line.

Example input

3
9
o.s…e.o
11
#…soe…#…
3
s#e

Example output

2
-1
0

题目大意就是有一排点,一共有五种点s点为开始点、e点为结束点、o为传送门、’.'点为可以正常通过的点,#为阻拦点不可以通过,问给你一段点你可以将. 点变成#点,至少需要改变多少个点才能让人不能从开始点到目标点,如果能则输出需要改变的点的数目不能则输出-1;

思路

一开始刚看到这道题我也很懵逼,后来仔细想一想要想从起始点出来或者进入终点只可能从该点的左边进或者右边,所以只要封住两边就可以达到效果(并且还只要封住少的一边就行了),大概的思路就是这样的,不过还有几个细节需要考虑,例如如果开始点和终点之间只有o或者之间相邻,那么无论如何也封不住所以要输出-1,另外因为我判断要封多少路是根据往左右走是否能直接碰到另外一个点或者是o1,就会有一个大概就是这样子** .o.s.o#.oe. **,可以看出如果按照上面的判断方法,左边封2右边封1选择1,但是右边是封不住的所以只能封左边2,就是这个地方让我一开始以为我的思路错了,还好最后想出来了,题目大概就是这样,问题不大。

代码
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
 
int main()
{
    freopen("portals.in","r",stdin);
    int n,i,j,k,a,s,e;
    string str;
 
    scanf("%d",&n);
 
    for(k=0; k<n; k++)
    {
        scanf("%d",&a);
        cin>>str;
 
        for(i=0; i<a; i++)
        {
            if(str[i]=='s')
                s=i;
            if(str[i]=='e')
                e=i;
        }
        int flags=0,flage=0;
        if(str[s-1]=='o'||str[s+1]=='o')
            flags=1;
        if(str[e-1]=='o'||str[e+1]=='o')
            flage=1;
        if(flage&&flags)
            printf("-1\n");
        else if(abs(s-e)==1)
            printf("-1\n");
 
            else
            {
                flags=0;
                flage=0;
                for(j=s; j>=0; j--)
                {
                    if(str[j]=='#')
                        break;
                    if(str[j]=='o')
                    {
                        flags++;
                        break;
                    }
                    if(str[j]=='e')
                    {
                        flags++;
                        break;
                    }
                }
                for(j=e; j>=0; j--)
                {
                    if(str[j]=='#')
                        break;
                    if(str[j]=='o')
                    {
                        flage++;
                        break;
                    }
                    if(str[j]=='s')
                    {
                        flage++;
                        break;
                    }
                }
                for(j=s; j<a; j++)
                {
                    if(str[j]=='#')
                        break;
                    if(str[j]=='o')
                    {
                        flags++;
                        break;
                    }
                    if(str[j]=='e')
                    {
                        flags++;
                        break;
                    }
                }
                for(j=e; j<a; j++)
                {
                    if(str[j]=='#')
                        break;
                    if(str[j]=='o')
                    {
                        flage++;
                        break;
                    }
                    if(str[j]=='s')
                    {
                        flage++;
                        break;
                    }
                }
                if((str[s-1]=='o'||str[s+1]=='o')&&flage==2)
                printf("2\n");
                else if((str[e-1]=='o'||str[e+1]=='o')&&flags==2)
                    printf("2\n");
                else
                printf("%d\n",min(flags,flage));
            }
    }
 
    return 0;
}

还有一道d题我比赛的时候没有写出来本来写d题的时候还有一个小时,我的思路大概就是贪心先判断分数最高的桶最多能进多少个球(首先桶直上方的肯定是可以的)左右两边如果有机关也是可以的,再往两边移动就是机关的位置是否在先前那个的上面依次类推直到不行为止),判断完分数最高的后判断第二高第三高就是这样,但是代码写到一半发现我可能是没有这个耐心写下去了,看来还是要多写一些才行。题目就在下面,是比赛后高年级一位大佬写的。

D. Carnival Slots

Problem Description

You go to the carnival and come across a nice little game. The carnival worker shows you the setup of the game, which can be represented as a 2-dimensional grid g with r rows and c columns. You are given the opportunity to change around the grid and maximize your score before the worker drops several balls into each column.

A cell in the ith row (from top) and the jth column (from left) is denoted by (i, j), and can be one of three different types of cells:

  1. ‘.’; a ball that enters this cell will go to cell (i + 1, j).
  2. ‘’; a ball that enters this cell will go to cell (i + 1, j + 1).
  3. ‘/’; a ball that enters this cell will go to cell (i + 1, j - 1).

You may change a cell of type 2 and 3 to any of the three types, and you can change as many cells as you want. Cells of type 1 can’t be changed.

Under the grid is aligned c buckets, where the ith bucket is below the ith column.
Each of the c buckets contains a score. For every ball that falls into a bucket, the score on that bucket is added to your total score and that ball stops. A ball that doesn’t fall into a bucket gets a score of 0.
You are given how many balls the worker will drop into each column. Balls are dropped one after the another such that no two balls will collide. After making the changes, what is the maximum score you can achieve?
Your only condition for the grid g is that it’s not allowed to have two adjacent cells in one row such that the left one is ‘’ and the right one is ‘/’.

Input

The first line of input contains a single integer T (1 ≤ T ≤ 5300), the number of test cases.

The first line of each test case contains two space-separated integers r and c (1 ≤ r, c ≤ 500), the dimensions of the grid.

The following line contains c space-separated integers b1, b2, …, bc (0 ≤ bi ≤ 108), where bi is the number of balls dropped into the ith column.

Each of the following r lines contains c characters, representing the grid. Each character is either ‘.’, ‘’, or ‘/’.

The last line of each test case contains c space-separated integers s1, s2, …, sc (0 ≤ si ≤ 108), where si is the score added after one ball drops into the ith bucket.

The sum of r × c over all test cases doesn’t exceed 4 × 106.

Output

For each test case, print on a single line the maximum score possible.

Example

input

2
3 3
1 2 1
…/
./.

10 5 20
1 2
100000000 100000000

1 100000000

output

70
10000000100000000

题目大意:n行m列网格,每列顶端会有b[i]个小球落下,每列底端有包含c[i]分数的桶,网格中s[i][j]=’.’ or ‘/’ or ‘‘分别代表该格朝向下、左下、右下。其中’’ 和’/‘可随意改变成其他任何方向,’.'无法更改。小球一个个的落下不存在碰撞,设最终落入i列桶的球个数为d[i],使得∑d[i]*c[i]最大。
思路:将桶按分数从大到小排序,从大分数桶向上倒着找,每次使得尽量更多的入球口滚入该桶。

代码

#include<bits/stdc++.h>

#define rep(a,b,c) for(ll a=b;a<=c;a++)

#define per(a,b,c) for(ll a=b;a>=c;a--)

#define pb push_back

#define mk make_pair

using namespace std;

typedef long long ll;

typedef double db;

const int inf = 0x3f3f3f3f;

const ll N = 5e2 + 5;

int n, m;

ll b[N];

struct node{

    ll x, id;

}c[N];

int vis[N][N];

char s[N][N];

bool cmp(node p, node q){

    return p.x > q.x;

}

ll ans, cnt;

void solve(ll id, ll val){

    queue<pair<int,int> > que;

    que.push(mk(n+1,id));

    while(!que.empty()){

        int R = que.front().first;

        int C = que.front().second;

        que.pop();

        if(R == 0){

            ans += b[C] * val;

            cnt++;

            continue;

        }

        if(!vis[R-1][C]){

            que.push(mk(R-1,C));

            vis[R-1][C] = 1;

        }

        if(C > 1 && s[R-1][C-1] != '.' && !vis[R-1][C-1]){

            que.push(mk(R-1,C-1));

            vis[R-1][C-1] = 1;

        }

        if(C < m && s[R-1][C+1] != '.' && !vis[R-1][C+1]){

            que.push(mk(R-1,C+1));

            vis[R-1][C+1] = 1;

        }

    }

}




int main(){

    freopen("balls.in","r",stdin);

    int T; scanf("%d", &T);

    while(T--){

        memset(vis,0,sizeof(vis));

        scanf("%d%d", &n, &m);

        rep(i,1,m) scanf("%lld", &b[i]);

        rep(i,1,n) scanf("%s", s[i] + 1);

        rep(i,1,m) s[0][i] = '.';

        rep(i,1,m){

            scanf("%lld", &c[i].x);

            c[i].id = i;

        }

        sort(c+1,c+1+m,cmp);

        ans = 0, cnt = 0;

        rep(i,1,m){

            solve(c[i].id, c[i].x);

            if(cnt == m) break;

        }

        printf("%lld\n", ans);

    }

    return 0;
    //from tyf

}

  1. 可能会有人想为什么碰到o也算,如果只有一个o怎么办或者这个o去不了另外一个点,其实我们只考虑它的最大情况最后在两边取小就行了; ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值