Google Code Jam Round 2 2018

Falling Balls

Problem

A certain toy consists of a grid of 2 or more columns and 1 or more rows, where each cell of the grid contains either a \ ramp or a /ramp, or is empty. The leftmost and rightmost columns are empty and the bottom row is also empty. Balls are dropped into the top row and fall vertically, sliding on ramps. To prevent balls from getting stuck, a cell with a \ ramp is never immediately to the left of a cell with a / ramp.

When a ball is dropped into the top row, it moves deterministically as follows:

  • A ball in an empty cell moves to the cell immediately below its current cell, unless it is in the bottom row, in which case it does not move any more.
  • A ball in a cell containing a \ ramp moves to the cell immediately below and to the right of its current cell.
  • A ball in a cell containing a / ramp moves to the cell immediately below and to the left of its current cell.

To see the mechanism to its full extent, the user drops exactly one ball into each column. Balls do not interfere with each other, and it is possible for a cell to contain multiple balls.

Your friend has a toy with C columns and an unknown number of rows. They just dropped one ball into the top row of each column, and waited for all balls to stop moving. Then, they counted how many balls ended up in each of the cells of the bottom row, and gave you those results... but you think it is possible that they made a mistake. Can you create a layout that is consistent with the results and uses as few rows as possible, or determine that no such layout exists?

For example, if your friend reported the values 3 0 0 2 0 1, one possible solution would be the following. (Note that it is not necessary to use a minimal number of ramps, or for every ramp to affect the balls.)

.//\..
./\./.
......

Here are the paths that the balls would take when falling through that grid:

Input

The first line of the input gives the number of test cases, TT test cases follow. Each begins with one line containing an integer C: the number of columns in your friend's falling ball toy. Then, there is one more line containing C integers Bi. The i-th of these integers represents the number of balls that ended up in the i-th cell from the left of the bottom row of your friend's falling ball toy, according to the data they gave you.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is either IMPOSSIBLE, or the number of rows in your layout, as described above. If y is not IMPOSSIBLE, output y more rows, representing the rows of your proposed falling ball toy layout, in order from top to bottom. Use . to represent a cell with no ramp, and \ or / to represent the ramps. The layout must obey all of the rules in the problem statement.

Limits

1 ≤ T ≤ 100.
0 ≤ Bi ≤ C, for all i.
The sum (over all i from 1 to C, inclusive) of all Bi values = C.
Time limit: 10 seconds per test set.
Memory limit: 1GB.

扫描二维码关注公众号,回复: 2526536 查看本文章

Test set 1 (Visible)

2 ≤ C ≤ 5.

Test set 2 (Hidden)

2 ≤ C ≤ 100.

Sample


Input 
 

Output 
 
3
4
1 1 1 1
3
0 2 1
6
3 0 0 2 0 1

Case #1: 1
....
Case #2: IMPOSSIBLE
Case #3: 3
.//\..
./\./.
......

Note that the last sample case would not appear in Test set 1.

The following layout is the only valid solution for Sample Case #1. (There must be at least one row, and including any more rows would make the solution use more rows than needed. It is not legal to include any ramps in the bottom row.)

....

In Sample Case #2, there is no way to prevent the leftmost ball from falling to the bottom of its column without adding a ramp, but ramps cannot be added to that column.

Sample Case #3 is the one described at the end of the problem statement. Note that the following invalid layout for Sample Case #3 breaks several rules: it has more rows than needed, it has ramps in the three illegal zones (left column, right column, bottom row), and it contains a \ ramp immediately to the left of a / ramp.

\\..\/
../.\/
./../.
..../.


题意:有c个球从同一水平线并排往下掉,经过一些左滑块或者右滑块(最左边和最右边没有滑块),给出掉到地上的每个格子的球数,反求在行数最少的情况下的滑块方式。


思路:前缀和,如果一段最小区间内区间内末行球数等于第一行原本的球数,那么应当是两端的球往里走。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long ll;
const int mod=1000000007;
int res[105];
int sum[105];
int g[105][105];
int main()
{
    int t;
    int c;
    scanf("%d",&t);
    for(int tt=1;tt<=t;tt++)
    {
        memset(g,0,sizeof(g));
        scanf("%d",&c);
        sum[0]=0;
        for(int i=1;i<=c;i++)
        {
            scanf("%d",&res[i]);
            sum[i]=sum[i-1]+res[i];
        }
        if(res[1]==0||res[c]==0||sum[c]!=c)
        {
            printf("Case #%d: IMPOSSIBLE\n",tt);
            continue;
        }
        int l=0;
        int len=0;
        for(int i=1;i<=c;i++)
        {
            if(sum[i]==i)
            {
                int x=0;
                for(int j=i;j>l;j--)  //右边的球往左走,直到到达某一点积累的球数小于它所需的球数
                {
                    x++;
                    if(res[j]<x)
                    {
                        int p=x-res[j];
                        len=max(len,p);
                        for(int k=1;k<=p;k++)
                        {
                            g[k][j]=2;
                        }
                        x-=res[j];
                    }
                    else if(res[j]>x)
                    {
                        break;
                    }
                }
                x=0;
                for(int j=l+1;j<=i;j++)  //左边的球往右走,直到到达某一点积累的球数小于它所需的球数
                {
                    x++;
                    if(res[j]<x)
                    {
                        int p=x-res[j];
                        len=max(len,p);
                        for(int k=1;k<=p;k++)
                        {
                            g[k][j]=1;
                        }
                        x-=res[j];
                    }
                    else if(res[j]>x)
                    {
                        break;
                    }
                }
                l=i;
            }
        }
        printf("Case #%d: %d\n",tt,len+1);
        for(int i=1;i<=len+1;i++)
        {
            for(int j=1;j<=c;j++)
            {
                if(g[i][j]==0)
                {
                    printf(".");
                }
                else if(g[i][j]==1)
                {
                    printf("\\");
                }
                else
                {
                    printf("/");
                }
            }
            printf("\n");
        }
    }
}




猜你喜欢

转载自blog.csdn.net/qq_25576697/article/details/80379538