BZOJ 1105: [POI2007]石头花园SKA

1105: [POI2007]石头花园SKA

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 628  Solved: 182
[Submit][Status][Discuss]

Description

  Blue Mary是一个有名的石头收藏家。迄今为止,他把他的藏品全部放在他的宫殿的地窖中。现在,他想将他
的藏品陈列在他的花园中。皇家花园是一个边长为1000000000单位的平行于坐标轴的正方形。对于每个石头,Blue
 Mary都有一个他想放置的坐标,然后将他告诉他的属下。不幸的是,他忘了告诉他们坐标的顺序(比如无法分辨(
x,y)和(y,x))。属下们,就自己决定了每个石头的具体位置。为了保护他的藏品,Blue Mary决定建造一个篱笆来
保护他们。为了美学的需要,篱笆也被设计为平行于坐标轴的矩形。如果花园的布局知道了,那么就可以知道最短
长度的篱笆的布局。他的属下们需要变换石头的坐标使得篱笆的长度最少。每个石头只能从(x,y)变换为(y,x),由
于每个石头的重量不一样。属下们希望他们移动的石头的重量和最少。

Input

  第一行包含一个数n,表示石头的数量(2<=n<=1000000),接下来n行分别描述n个石头的初始坐标和重量xi,y
i,mi。(0<=xi,yi<=1000000000,1<=mi<=2000)

Output

  包含两行,第一行包含两个数由一个空格分割。最小的篱笆长度和最小的移动的石子的重量和。第二行为一个
01字符串,第i个字符为1表示要改变第i个石头的位置。0表示不改变。

Sample Input

5
2 3 400
1 4 100
2 2 655
3 4 100
5 3 277

Sample Output

10 200
01010

HINT

 

 

Source

 
[Submit][Status][Discuss]

 

分析

篱笆的长度最小是第一目标,应当优先考虑。易知,当所有石头的坐标都满足x<=y的时候,即全部在y=x直线的一侧之时,一定能够得到最小的周长,这时的周长就是第一个答案。

而满足这一周长的方式不止一种,可以将这个矩形关于y=x直线做对称,总共有四种可能的情况,全部枚举一遍即可。

代码

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7  
 8 #define ri register int
 9  
10 #define lim 100000000
11  
12 char *c = new char[lim];
13  
14 template <class T>
15 void read(T &x)
16 {
17     x = 0;
18      
19     while (*c < '0')++c;
20      
21     while (*c >= '0')
22         x = x*10 + *c++ - '0';
23 }
24  
25 #define N 1000005
26 #define inf 2e9 + 7
27  
28 int n;
29 int x[N];
30 int y[N];
31 int w[N];
32  
33 int ans = inf;
34  
35 bool vis[N], use[N];
36  
37 void calculate(int lx, int ly, int rx, int ry)
38 {   
39     ri res = 0; memset(vis, 0, sizeof(vis));
40      
41     #define judge(X, Y) (X >= lx && X <= rx && Y >= ly && Y <= ry)
42      
43     for (ri i = 1; i <= n; ++i)
44     {
45         if (judge(x[i], y[i]))
46             continue;
47         if (judge(y[i], x[i]))
48             vis[i] = 1, res += w[i];
49         else return;
50     }
51      
52     if (res < ans)
53         ans = res, memcpy(use, vis, sizeof(use));
54 }
55  
56 signed main(void)
57 {
58      
59     fread(c, 1, lim, stdin);
60      
61     read(n);
62      
63     for (ri i = 1; i <= n; ++i)
64         read(x[i]), read(y[i]), read(w[i]);
65          
66     ri lx, ly, rx, ry;
67      
68     lx = ly = inf, rx = ry = 0;
69          
70     for (ri i = 1; i <= n; ++i)
71     {
72         if (x[i] < y[i])
73         {
74             if (x[i] < lx)lx = x[i];
75             if (y[i] < ly)ly = y[i];
76             if (x[i] > rx)rx = x[i];
77             if (y[i] > ry)ry = y[i];
78         }
79         else
80         {
81             if (y[i] < lx)lx = y[i];
82             if (x[i] < ly)ly = x[i];
83             if (y[i] > rx)rx = y[i];
84             if (x[i] > ry)ry = x[i];
85         }
86     }
87      
88     calculate(lx, ly, rx, ry);
89     calculate(lx, ly, ry, rx);
90     calculate(ly, lx, rx, ry);
91     calculate(ly, lx, ry, rx);
92      
93     printf("%lld %d\n", 2LL*(rx + ry - lx - ly), ans);
94      
95     for (ri i = 1; i <= n; ++i)putchar(use[i] ? '1' : '0');
96 }
BZOJ_1105.cpp

 

@Author: YouSiki

posted @ 2016-11-22 23:38  YouSiki  阅读(446)  评论(0编辑  收藏  举报