Cutting Corners (acm 1996)
地址连接:http://www.karrels.org/Ed/ACM/96/ccorners.html
刚开始做这题时候,没作对,后来优化了下代码,问了下pozen,测试代码通过,只是没有地方提交。。。
寻路是dp(动态规划)。。其实可以成优化成很小,直接是求所有点中的其中2点距离。
1996 ACM Scholastic Programming Contest Finals
sponsored by Microsoft ®
Problem C
Cutting Corners
Input file: corner.in
代码如下:
1
# include
<
iostream
>
2
# include
<
cmath
>
3
using
namespace
std;
4
5
#define
MAXRECT 22
6
7
struct
Point
8
{
9
double x,y;
10
bool operator == (Point & r)
11
{
12
return (x==r.x && y==r.y);
13
}
14
}
;
15
16
struct
Rect
17
{
18
Point p[4];
19
}
;
20
21
Point reg[
4
*
MAXRECT
+
2
];
//
最多可能出现的点,包括起点和终点
22
Rect rect[MAXRECT];
//
矩形
23
double
arr_point[
4
*
MAXRECT
+
2
][
4
*
MAXRECT
+
2
];
//
枚举所有点之间的距离
24
int
Count
=
0
;
25
26
27
double
disten(Point a , Point b)
28
{
29
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
30
}
31
//
判断线段是否相交
32
bool
IsLineSegmentCross(Point pFirst1, Point pFirst2, Point pSecond1, Point pSecond2)
33
{
34
//每个线段的两点都在另一个线段的左右不同侧,则能断定线段相交
35
//公式对于向量(x1,y1)->(x2,y2),判断点(x3,y3)在向量的左边,右边,还是线上.
36
//p=x1(y3-y2)+x2(y1-y3)+x3(y2-y1).p<0 左侧, p=0 线上, p>0 右侧
37
if(pFirst1 == pSecond1 || pSecond2 == pFirst1)
38
return false;
39
if(pFirst2 == pSecond1 || pSecond2 == pFirst2)
40
return false;
41
long Linep1,Linep2;
42
//判断pSecond1和pSecond2是否在pFirst1->pFirst2两侧
43
Linep1 = pFirst1.x * (pSecond1.y - pFirst2.y) +pFirst2.x * (pFirst1.y - pSecond1.y) + pSecond1.x *
44
45
(pFirst2.y - pFirst1.y);
46
Linep2 = pFirst1.x * (pSecond2.y - pFirst2.y) + pFirst2.x * (pFirst1.y - pSecond2.y)+ pSecond2.x *
47
48
(pFirst2.y - pFirst1.y);
49
if ( ((Linep1 ^ Linep2) >= 0 ) && !(Linep1==0 && Linep2==0))//符号位异或为0:pSecond1和pSecond2在pFirst1-
50
51
>pFirst2同侧
52
{
53
return false;
54
}
55
//判断pFirst1和pFirst2是否在pSecond1->pSecond2两侧
56
Linep1 = pSecond1.x * (pFirst1.y - pSecond2.y) +
57
pSecond2.x * (pSecond1.y - pFirst1.y) +
58
pFirst1.x * (pSecond2.y - pSecond1.y);
59
Linep2 = pSecond1.x * (pFirst2.y - pSecond2.y) +
60
pSecond2.x * (pSecond1.y - pFirst2.y) +
61
pFirst2.x * (pSecond2.y - pSecond1.y);
62
if ( ((Linep1 ^ Linep2) >= 0 ) && !(Linep1==0 && Linep2==0))//符号位异或为0:pFirst1和pFirst2在pSecond1-
63
64
>pSecond2同侧
65
{
66
return false;
67
}
68
//否则判为相交
69
return true;
70
}
71
72
bool
Piont2_in_Rcet(Point a, Point b , Rect c)
//
点a,b是否经过矩形c
73
{
74
for(int i = 0 ; i < 4 ; i++)
75
{
76
if(IsLineSegmentCross(a,b,c.p[i%4],c.p[(i+1)%4]))
77
return true;
78
}
79
return false; // 不再矩形中
80
}
81
82
//
求出所有顶点之间的距离
83
void
find_path()
84
{
85
for(int i = 0; i < Count-1 ; i++)
86
{
87
for(int j = i+1 ; j < Count ; j++)
88
{
89
int flag = 0;
90
for(int k = 0 ; k < 4 ; k++)
91
{
92
if(Piont2_in_Rcet(reg[i],reg[j],rect[k]))
93
{
94
arr_point[i][j] = -1;
95
flag = 1;
96
break;
97
}
98
}
99
if(!flag)
100
{
101
arr_point[j][i] = arr_point[i][j] = disten(reg[i],reg[j]);
102
103
}
104
}
105
}
106
}
107
108
//
dp (n^3) 求解
109
void
GetShortest()
110
{
111
for (int i = 0 ; i < Count ; i++)
112
{
113
for (int j = 0 ; j < Count ; j++)
114
{
115
for (int k = 0 ; k < Count ; k++ )
116
{
117
if( (arr_point[i][j] !=-1) && arr_point[j][k] !=-1 && (arr_point[i][k]==-1 ||
118
119
arr_point[i][k] > (arr_point[i][j]+arr_point[j][k])))
120
{
121
// if(i==0)
122
// cout <<"i =" <<i <<" j = "<< j <<" k="<<k<<" len = "<<arr_point[i][k]<<endl;
123
arr_point[i][k] = arr_point[i][j] + arr_point[j][k];
124
}
125
}
126
}
127
}
128
}
129
int
main()
130
{
131
132
//freopen("corner.in","r",stdin);
133
int n,i,j;
134
double a,b,c,d,e,f;
135
int m = 1;
136
while (cin >> n && n != -1)
137
{
138
memset(reg,0,sizeof(reg));
139
memset(rect,0,sizeof(rect));
140
cin >> reg[0].x >> reg[0].y >> reg[1].x >> reg[1].y;
141
Count = 2;
142
int index = 2;
143
for(i = 0 ; i < n ; i++)
144
{
145
cin >> a >> b >> c >> d >> e >>f;
146
reg[index].x = rect[i].p[0].x = a;
147
reg[index].y = rect[i].p[0].y = b;
148
reg[1+index].x = rect[i].p[1].x = c;
149
reg[1+index].y = rect[i].p[1].y = d;
150
reg[2+index].x = rect[i].p[2].x = e;
151
reg[2+index].y = rect[i].p[2].y = f; // 4个矩形赋值
152
153
reg[index+3].x = rect[i].p[3].x = a+e - c; // 根据对称性
154
reg[index+3].y = rect[i].p[3].y = b+f - d;
155
156
index +=4;
157
Count +=4;
158
} // 读取数据
159
160
161
for(i = 0 ; i < 4*MAXRECT+2 ; i++)
162
for(j = 0 ; j < 4*MAXRECT+2 ; j++)
163
arr_point[i][j] = -1; // 任意2点不可达到
164
165
166
find_path();
167
GetShortest();
168
//cout << "route distance: " << arr_point[0][1] <<endl;
169
printf("Scenario #%d\n route distance: %.2f\n",m++,arr_point[0][1]);
170
}
171
return 0;
172
}
173

2

3

4

5

6

7

8



9

10

11



12

13

14

15

16

17



18

19

20

21

22

23

24

25

26

27

28



29

30

31

32

33



34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52



53

54

55

56

57

58

59

60

61

62

63

64

65



66

67

68

69

70

71

72

73



74

75



76

77

78

79

80

81

82

83

84



85

86



87

88



89

90

91



92

93



94

95

96

97

98

99

100



101

102

103

104

105

106

107

108

109

110



111

112



113

114



115

116



117

118

119

120



121

122

123

124

125

126

127

128

129

130



131

132

133

134

135

136

137



138

139

140

141

142

143

144



145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173
