贪心
经过11 年的韬光养晦,某国研发出了一种新的导弹拦截系统,凡是与它的距离不超过其工作半径的导弹都能够被它成功拦截。当工作半径为0 时,则能够拦截与它位置恰好相同的导弹。但该导弹拦截系统也存在这样的缺陷:每套系统每天只能设定一次工作半径。而当天的使用代价,就是所有系统工作半径的平方和。
某天,雷达捕捉到敌国的导弹来袭。由于该系统尚处于试验阶段,所以只有两套系统投入工作。如果现在的要求是拦截所有的导弹,请计算这一天的最小使用代价。
数据范围
对于10%的数据,N = 1
对于20%的数据,1 ≤ N ≤ 2
对于40%的数据,1 ≤ N ≤ 100
对于70%的数据,1 ≤ N ≤ 1000
对于100%的数据,1 ≤ N ≤ 100000,且所有坐标分量的绝对值都不超过1000。
第一行包含4 个整数x1、y1、x2、y2,每两个整数之间用一个空格隔开,表示这两套导弹拦截系统的坐标分别为(x1, y1)、(x2, y2)。
第二行包含1 个整数N,表示有N 颗导弹。接下来N 行,每行两个整数x、y,中间用一个空格隔开,表示一颗导弹的坐标(x, y)。不同导弹的坐标可能相同。
输出只有一行,包含一个整数,即当天的最小使用代价。
0 0 10 0
2
-3 3
10 0
18
两个点(x1, y1)、(x2, y2)之间距离的平方是(x1− x2)^2+(y1−y2)^2。
两套系统工作半径r1、r2 的平方和,是指r1、r2 分别取平方后再求和,即r1^2+r2^2。
思路:
贪心,把所有导弹到两个拦截装置的距离求出来,然后按照与第一个装置的距离为关键字进行排序,然后从大到小算出两个装置的设置半径,最后输出结果
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 6 using namespace std; 7 const int maxn = 10000000; 8 int n,xa,xb,ya,yb,total = maxn; 9 int x[maxn],y[maxn]; 10 11 struct bomb{ 12 int s1,s2,num; 13 }; 14 bomb a[maxn]; 15 16 bool cmp(bomb n1,bomb n2){ 17 if(n1.s1 < n2.s1) return true; 18 else return false; 19 } 20 int main(){ 21 cin>>xa>>ya>>xb>>yb>>n; 22 23 24 int r1 = 0,r2 = 0,temp = 0,total = maxn; 25 for(r1 = 0;r1 < n;r1++){ 26 cin>>x[r1]>>y[r1]; 27 a[r1].s1 = (x[r1] - xa) * (x[r1] - xa) + (y[r1] - ya) * (y[r1] - ya); 28 a[r1].s2 = (x[r1] - xb) * (x[r1] - xb) + (y[r1] - yb) * (y[r1] - yb); 29 a[r1].num = r1; 30 31 } 32 33 sort(a,a+n,cmp); 34 r1 = n -1; 35 r2 = 0; 36 37 for(r1 = n - 1;r1 >= 0;r1--){ 38 r2 = r1 + 1; 39 if(a[r2].s2 > temp && r2 < n) temp = a[r2].s2; 40 41 42 if(total > temp + a[r1].s1) total = temp + a[r1].s1; 43 } 44 if(a[0].s2 > temp) temp = a[0].s2; 45 if(total > temp) total = temp; 46 47 48 cout<<total; 49 return 0; 50 }
Wikioi 1001 舒适的线路
Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。
Z小镇附近共有
N(1<N≤500)个景点(编号为1,2,3,…,N),这些景点被M(0<M≤5000)条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。频繁的改变速度使得游客们很不舒服,因此大家从一个景点前往另一个景点的时候,都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。
第一行包含两个正整数,N和M。
接下来的M行每行包含三个正整数:x,y和v(1≤x,y≤N,0 最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
样例1
4 2
1 2 1
3 4 2
1 4
样例2
3 3
1 2 10
1 2 5
2 3 8
1 3
样例3
3 2
1 2 2
2 3 4
1 3
样例1
IMPOSSIBLE
样例2
5/4
样例3
2
N(1<N≤500)
M(0<M≤5000)
Vi在int范围内
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 7 using namespace std; 8 struct Edge{ 9 int x; 10 int y; 11 int v; 12 }; 13 const int maxn = 100000; 14 int n,m,s,t,pre[maxn]; 15 Edge edge[maxn]; 16 void init(){ 17 cin>>n>>m; 18 for(int i = 0; i < m;i++){ 19 cin>>edge[i].x>>edge[i].y>>edge[i].v; 20 21 } 22 cin>>s>>t; 23 for(int i = 1;i <= n;i++) pre[i] = i; 24 } 25 bool cmp(Edge a,Edge b){ 26 return a.v > b.v; 27 } 28 int gcd(int a,int b) 29 { 30 if (a < b) 31 swap(a, b); 32 return b == 0 ? a : gcd(b, a % b); 33 } 34 int find(int x) 35 { 36 int r=x; 37 while ( pre[r ] != r ) 38 r=pre[r ]; 39 40 int i=x , j ; 41 while( i != r ) 42 { 43 j = pre[ i ]; 44 pre[ i ]= r ; 45 i=j; 46 } 47 return r ; 48 } 49 50 51 void join(int x,int y) 52 53 { 54 int fx=find(x),fy=find(y); 55 if(fx!=fy) 56 pre[fx ]=fy; 57 } 58 59 void print(int so,int mo){ 60 61 if(so == -1 && mo == -1) cout<<"IMPOSSIBLE"<<endl; 62 else { 63 int g = gcd(so,mo); 64 if(mo/g != 1)cout<<so/g<<"/"<<mo/g<<endl; 65 else cout<<so/g<<endl; 66 } 67 68 } 69 void work(){ 70 double ans_max,ans_min,fx,fy; 71 double rate = 100000000; 72 int son = -1,mother = -1; 73 sort(edge,edge+m,cmp); 74 for(int i = 0;i < m;i++){ 75 for(int o = 1;o <= n;o++) pre[o] = o; 76 rate = 100000000; 77 ans_max = edge[i].v; 78 ans_min = edge[i].v; 79 fx = -1; 80 fy = -1; 81 for(int j = i;j < m;j++){ 82 join(edge[j].x,edge[j].y); 83 ans_min = edge[j].v; 84 int fx=find(s),fy=find(t); 85 if(fx != fy){ 86 ans_min = edge[j].v; 87 }else{ 88 if(ans_max / ans_min < rate){ 89 rate = ans_max / ans_min; 90 son = ans_max; 91 mother = ans_min; 92 } 93 continue; 94 } 95 } 96 } 97 print(son,mother); 98 99 100 } 101 102 int main(){ 103 init(); 104 work(); 105 return 0; 106 }
Wikioi 1198 国王游戏
恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
第一行包含一个整数 n,表示大臣的人数。
第二行包含两个整数a和b,之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来n行,每行包含两个整数a和b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。
输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的
金币数。
3
1 1
2 3
7 4
4 6
2
【输入输出样例说明】
按 1、2、3号大臣这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;
按 1、3、2这样排列队伍,获得奖赏最多的大臣所获得金币数为2;
按 2、1、3这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;
按 2、3、1这样排列队伍,获得奖赏最多的大臣所获得金币数为 9;
按 3、1、2这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;
按 3、2、1这样排列队伍,获得奖赏最多的大臣所获得金币数为 9。
因此,奖赏最多的大臣最少获得 2 个金币,答案输出 2。
【数据范围】
对于20%的数据,有1≤ n≤ 10,0 < a、b < 8;
对于40%的数据,有1≤ n≤20,0 < a、b < 8;
对于60%的数据,有1≤ n≤100;
对于60%的数据,保证答案不超过 10^9;
对于100%的数据,有 1 ≤ n ≤1,000,0 < a、b < 10000。
思路:
(摘自夏令营课件)
首先,相邻两个人交换位置,对其他人获得的奖赏没有影响。 设A、B相邻,A的左右手分别是a、b, B的左右手分别是c、d。A、B之前大臣左手的乘积是t。 A在B前,A获得t/b,B获得at/d。 B在A前,A获得ct/b,B获得t/d。 因为t/b<ct/b,t/d<at/d 所以总的最大值是at/d或ct/b
a/d>c/b,即ab>cd时, A在B前会更大,所以让B在A前 a/d<c/b,即ab<cd时, B在A前会更大,所以让A在B前 所以按左右手上数的乘积从小到大排序。
代码:
(注意高精度)
1 #include <cstdio> 2 #include<algorithm> 3 #include <cmath> 4 #include <iostream> 5 #include <cstring> 6 7 using namespace std; 8 9 const int P=10000,L=5000,W=4; 10 char s[L*W]; 11 struct Big 12 { 13 int len;int data[L];bool fu; 14 void clear() 15 { 16 memset(data,0,sizeof(data)); 17 len=0;fu=false; 18 } 19 int& operator [] (int k) 20 { 21 return data[k]; 22 } 23 void operator = (int k) 24 { 25 clear(); 26 if (k<0) fu=true,k=-k;else fu=false; 27 len=0; 28 while (k) data[++len]=k%P,k/=P; 29 if (len==0) len=1; 30 } 31 bool operator < (Big b) 32 { 33 bool t=false; 34 if (fu && !b.fu) return true; 35 if (!fu && b.fu) return false; 36 if (fu && b.fu) t=true; 37 if (len<b.len) return true^t; 38 if (len>b.len) return false^t; 39 for (int i=len;i;--i) 40 { 41 if (data[i]<b[i]) return true^t; 42 if (data[i]>b[i]) return false^t; 43 } 44 return false; 45 } 46 bool operator <= (Big b) 47 { 48 bool t=false; 49 if (fu && !b.fu) return true; 50 if (!fu && b.fu) return false; 51 if (fu && b.fu) t=true; 52 if (len<b.len) return true^t; 53 if (len>b.len) return false^t; 54 for (int i=len;i;--i) 55 { 56 if (data[i]<b[i]) return true^t; 57 if (data[i]>b[i]) return false^t; 58 } 59 return true; 60 } 61 bool operator > (Big b) 62 { 63 bool t=false; 64 if (fu && !b.fu) return false; 65 if (!fu && b.fu) return true; 66 if (fu && b.fu) t=true; 67 if (len<b.len) return false^t; 68 if (len>b.len) return true^t; 69 for (int i=len;i;--i) 70 { 71 if (data[i]<b[i]) return false^t; 72 if (data[i]>b[i]) return true^t; 73 } 74 return false; 75 } 76 bool operator >= (Big b) 77 { 78 bool t=false; 79 if (fu && !b.fu) return false; 80 if (!fu && b.fu) return true; 81 if (fu && b.fu) t=true; 82 if (len<b.len) return false^t; 83 if (len>b.len) return true^t; 84 for (int i=len;i;--i) 85 { 86 if (data[i]<b[i]) return false^t; 87 if (data[i]>b[i]) return true^t; 88 } 89 return true; 90 } 91 bool operator == (Big b) 92 { 93 if (fu!=b.fu) return false; 94 if (len<b.len) return false; 95 if (len>b.len) return false; 96 for (int i=len;i;--i) 97 if (data[i]!=b[i]) return false; 98 return true; 99 } 100 bool operator == (int k) 101 { 102 if (k<0) 103 { 104 if (!fu) return false; 105 k=-k; 106 } else if (fu) return false; 107 if (k>=P) 108 { 109 Big b;b=k; 110 return *this==b; 111 } 112 else return len==1 && data[1]==k; 113 } 114 bool operator != (Big b) 115 { 116 if (fu!=b.fu) return true; 117 if (len<b.len) return true; 118 if (len>b.len) return true; 119 for (int i=len;i;--i) 120 if (data[i]!=b[i]) return true; 121 return false; 122 } 123 bool operator != (int k) 124 { 125 if (k<0) 126 { 127 if (!fu) return true; 128 k=-k; 129 } else if (fu) return true; 130 if (k>=P) 131 { 132 Big b;b=k; 133 return *this!=b; 134 } 135 else return !(len==1 && data[1]==k); 136 } 137 Big operator + (Big b) 138 { 139 Big a=*this,c;c.clear(); 140 if (a.fu && b.fu) 141 { 142 a.fu=false;b.fu=false;c=a+b; 143 if (c.len!=1 || c[1]!=0) c.fu=true; 144 return c; 145 } 146 if (a.fu && !b.fu) 147 {a.fu=false;return b-a;} 148 if (!a.fu && b.fu) 149 {b.fu=false;return a-b;} 150 a.len=max(a.len,b.len); 151 for (int i=1;i<=a.len;++i) 152 { 153 a[i+1]+=(a[i]+b[i])/P; 154 a[i]=(a[i]+b[i])%P; 155 } 156 if (a[a.len+1]) ++a.len; 157 while (a[a.len]==0 && a.len>1) --a.len; 158 return a; 159 } 160 Big operator + (int k) 161 { 162 Big a=*this,b;b=k; 163 return a+b; 164 } 165 Big operator - (Big b) 166 { 167 Big a=*this,c;c.clear(); 168 if (a.fu && !b.fu) 169 { 170 a.fu=false;b.fu=false;c=a+b; 171 if (c.len!=1 || c[1]!=0) c.fu=true; 172 return c; 173 } 174 if (a.fu && b.fu) 175 { 176 a.fu=false;b.fu=false;return b-a; 177 } 178 if (!a.fu && b.fu) 179 { 180 b.fu=false; return a+b; 181 } 182 if (a<b) swap(a,b),a.fu=true;else a.fu=false; 183 for (int i=1;i<=a.len;++i) 184 { 185 if (a[i]<b[i]) a[i]+=P,--a[i+1]; 186 a[i]-=b[i]; 187 } 188 while (a[a.len]==0 && a.len>1) --a.len; 189 if (a.len==1 && a[1]==0) a.fu=false; 190 return a; 191 } 192 Big operator - (int k) 193 { 194 Big a=*this,b;b=k; 195 return a-b; 196 } 197 Big operator * (Big b) 198 { 199 Big c;c.clear(); 200 c.len=len+b.len-1; 201 for (int i=1;i<=len;++i) 202 for (int j=1;j<=b.len;++j) 203 { 204 c[i+j-1]+=data[i]*b[j]; 205 c[i+j]+=c[i+j-1]/P; 206 c[i+j-1]%=P; 207 } 208 if (c[c.len+1]) ++c.len; 209 while (c[c.len]==0 && c.len>1) --c.len; 210 c.fu=fu^b.fu; 211 if (c.len==1 && c[1]==0) c.fu=false; 212 return c; 213 } 214 Big operator * (int k) 215 { 216 Big a=*this; 217 if (k<0) a.fu=!a.fu,k=-k; 218 if (k>=P) 219 { 220 Big b;b=k; 221 return a*b; 222 } 223 for (int i=1;i<=a.len;++i) a[i]*=k; 224 for (int i=1;i<=a.len;++i) 225 a[i+1]+=a[i]/P,a[i]%=P; 226 while (a[a.len+1]) 227 { 228 ++a.len; 229 a[a.len+1]=a[a.len]/P; 230 a[a.len]%=P; 231 } 232 while (a[a.len]==0 && a.len>1) --a.len; 233 if (a.len==1 && a[1]==0) a.fu=false; 234 return a; 235 } 236 Big operator / (int k) 237 { 238 Big a=*this;int g=0; 239 if (k<0) a.fu=!a.fu,k=-k; 240 for (int i=a.len;i;--i) 241 { 242 a[i]+=g*P; 243 g=a[i]%k; 244 a[i]/=k; 245 } 246 while (a[a.len]==0 && a.len>1) --a.len; 247 if (a.len==1 && a[1]==0) a.fu=false; 248 return a; 249 } 250 Big operator % (int k) 251 { 252 Big b;b=k; 253 return *this%b; 254 } 255 Big operator / (Big b) 256 { 257 Big c,d;c=0;d=0;c.fu=fu^b.fu;b.fu=false; 258 for (int i=len;i;--i) 259 { 260 d=d*P+data[i]; 261 int ans=0,l=0,r=P-1; 262 while (l<=r) 263 { 264 int mid=(l+r)>>1; 265 if (b*mid<=d) ans=mid,l=mid+1; 266 else r=mid-1; 267 } 268 c[i]=ans; 269 d=d-b*c[i]; 270 } 271 c.len=len; 272 while (c[c.len]==0 && c.len>1) --c.len; 273 return c; 274 } 275 Big operator % (Big b) 276 { 277 Big c,d;c=0;d=0;c.fu=fu^b.fu;b.fu=false; 278 for (int i=len;i;--i) 279 { 280 d=d*P+data[i]; 281 int ans=0,l=0,r=P-1; 282 while (l<=r) 283 { 284 int mid=(l+r)>>1; 285 if (b*mid<=d) ans=mid,l=mid+1; 286 else r=mid-1; 287 } 288 c[i]=ans; 289 d=d-b*c[i]; 290 } 291 c.len=len; 292 while (c[c.len]==0 && c.len>1) --c.len; 293 d=*this-b*c; 294 return d; 295 } 296 Big operator ^ (int t) 297 { 298 Big a=*this,ans;ans=1; 299 while (t) 300 { 301 if (t&1) ans=ans*a;t>>=1;a=a*a; 302 } 303 return ans; 304 } 305 void read() 306 { 307 scanf("%s",s); 308 clear(); 309 len=1; 310 int pow=1,t=1,l=strlen(s),stop=0; 311 if (s[0]=='-') fu=true,stop=1; 312 for (int i=l-1;i>=stop;--i) 313 { 314 if (t>W) t=pow=1,++len; 315 data[len]+=pow*(s[i]-'0'); 316 ++t,pow*=10; 317 } 318 } 319 void write() 320 { 321 if (fu) printf("%c",'-'); 322 printf("%d",data[len]); 323 for (int i=len-1;i;--i) 324 { 325 if (data[i]<10) putchar('0'); 326 if (data[i]<100) putchar('0'); 327 if (data[i]<1000) putchar('0'); 328 printf("%d",data[i]); 329 } 330 } 331 void writeln() 332 { 333 write();printf("\n"); 334 } 335 } ; 336 struct Man{ 337 int l; 338 int r; 339 Big sum; 340 }; 341 bool cmp(Man a,Man b){ 342 return (a.l * a.r) < (b.l * b.r); 343 } 344 Big ans,lft; 345 Man man[1005]; 346 int main(){ 347 int n,fl,fr; 348 cin>>n; 349 cin>>fl>>fr; 350 for(int i = 0;i < n;i++){ 351 cin>>man[i].l>>man[i].r; 352 man[i].sum = man[i].l * man[i].r; 353 } 354 sort(man,man + n,cmp); 355 ans = 0; 356 lft = fl; 357 for(int i = 0;i < n;i++){ 358 if(lft * man[i].r > ans) ans = lft / man[i].r; 359 lft = lft * man[i].l; 360 } 361 if(ans == 0) cout<<1<<endl; 362 else ans.writeln(); 363 364 return 0; 365 }
田忌赛马,某个普及组题