湖南省第八届程序设计竞赛H

Problem H. Tin Cutter II

 

In a Tin Cutting factory there isa machine for cutting parts from tin plates. It has an extraordinarily sharpknife able to make horizontal or vertical segment cuts in the tin plates. Eachcutting process consists of a sequence of such cuts. Each segment cut is givenby its endpoints that are always located inside the tin plate. During the cuttingprocess some parts of tin plate can fall out and so some holes in the plate canemerge.

 

Factory management needs topredict the length of visible border lines at the end of the given sequence ofcuts. Write a program that answers this question.

 

Here arefour examples:

 

The firstrow in the picture are four cuttings and the second row are their correspondingresulting plates. Each gray area is a separate hole, and thick lines arevisible border lines after cutting. There are 2, 2, 1, 1 holes respectively(from left to right), and the length of visible border lines are 8, 26, 12, 20respectively.

 

Input

The first line of input contains a single integer T (T<=100),the number of test cases. The first line of each test case contains aninteger n (1<=n<=100), the number ofsegment cuts. Each of the following n lines describe a segmentcut with four integers x1, y1, x2, y2 that means asegment cut from (x1,y1) to (x2,y2) (0<=x1,y1,x2,y2<=10000).The segment is always horizontal or vertical.

 

Output

For each test case, print the total lengthof the border lines.


 

Sample Input                               Output forSample Input

4

6

0 0 1 0

1 0 1 2

1 2 2 2

2 2 2 1

2 1 0 1

0 1 0 0

9

0 0 4 0

4 0 4 4

4 4 0 4

0 4 0 0

6 1 8 1

8 1 8 3

8 3 6 3

6 3 6 1

2 2 7 2

8

0 1 3 1

3 1 3 2

3 2 0 2

0 2 0 1

1 0 2 0

2 0 2 3

2 3 1 3

1 3 1 0

8

0 1 4 1

4 1 4 4

4 4 0 4

0 4 0 1

3 0 6 0

6 0 6 2

6 2 3 2

3 2 3 0

8

26

12

20

代码:
// Rujia Liu
#include<cstdio>
#include<cassert>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 100*2 + 5;
const int maxv = 10000 + 5;
const int RIGHT = 0;
const int UP = 1;

int line[maxn][maxn][2]; // RIGHT and UP
int alive[maxn][maxn]; // alive[x][y] == 1 iff the square whose left-bottom corner is (x,y), is alive

int npx, npy; // number of points in x and y directions. points are numbered 1 to np*. squares are numbered 0 to np*
int xp[maxn], yp[maxn], idx[maxv], idy[maxv]; // xp[idx[v]] = v.

void dfs(int x, int y) {
  if(alive[x][y]) return;
  alive[x][y] = 1;
  if(y < npy && !line[x][y+1][RIGHT]) dfs(x, y+1); // UP
  if(y > 0   && !line[x][y  ][RIGHT]) dfs(x, y-1); // DOWN
  if(x > 0   && !line[x][y  ][UP]) dfs(x-1, y); // LEFT
  if(x < npx && !line[x+1][y][UP]) dfs(x+1, y); // RIGHT
}

int main() {
  int T;
  scanf("%d", &T);
  while(T--) {
    int n, x1[maxn], y1[maxn], x2[maxn], y2[maxn], vis[maxv];
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
      scanf("%d%d%d%d", &x1[i], &y1[i], &x2[i], &y2[i]);
      if(x1[i] == x2[i]) {
        assert(y1[i] != y2[i]);
        if(y1[i] > y2[i]) swap(y1[i], y2[i]);
      } else {
        assert(y1[i] == y2[i]);
        if(x1[i] > x2[i]) swap(x1[i], x2[i]);
      }
    }

    // discrete x
    memset(vis, 0, sizeof(vis));
    for(int i = 0; i < n; i++) vis[x1[i]] = vis[x2[i]] = 1;
    npx = 0;
    for(int i = 0; i < maxv; i++) if(vis[i]) {
      xp[++npx] = i;
      idx[i] = npx;
    }
    
    // discrete y
    memset(vis, 0, sizeof(vis));
    for(int i = 0; i < n; i++) vis[y1[i]] = vis[y2[i]] = 1;
    npy = 0;
    for(int i = 0; i < maxv; i++) if(vis[i]) {
      yp[++npy] = i;
      idy[i] = npy;
    }

    // draw lines in discrete grid
    memset(line, 0, sizeof(line));
    for(int i = 0; i < n; i++) {
      if(x1[i] != x2[i]) for(int x = idx[x1[i]]; x < idx[x2[i]]; x++) line[x][idy[y1[i]]][RIGHT] = 1;
      if(y1[i] != y2[i]) for(int y = idy[y1[i]]; y < idy[y2[i]]; y++) line[idx[x1[i]]][y][UP] = 1;
    }

    // floodfill
    memset(alive, 0, sizeof(alive));
    dfs(0, 0);

    // accumulate answer
    int ans = 0;
    int lost = 0;
    for(int x = 1; x <= npx; x++)
      for(int y = 1; y <= npy; y++) {
        if(!alive[x][y]) lost++;
        if(line[x][y][RIGHT] && (alive[x][y] || alive[x][y-1])) ans += xp[x+1] - xp[x]; // check RIGHT
        if(line[x][y][UP]    && (alive[x][y] || alive[x-1][y])) ans += yp[y+1] - yp[y]; // check UP
      }
    printf("%d\n", ans);
  }
  return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值