标签:
T1-UVa-采矿
OJ:http://acm.hust.edu.cn/vjudge/problem/40564
某天gameboy玩魔兽RPG。有一个任务是在一个富含金矿的圆形小岛上建一个基地,以最快的速度采集完这个小岛上的所有金矿。这个小岛上有n(0<n<1000000)个金矿,每个金矿的矿藏量是相等的。而且这个小岛的地势非常平坦,所以基地可以建在小岛的任何位置,每个金矿的采矿速度只跟矿藏到基地的路程长度有关。为了不让这个任务太无聊,游戏设计者对这个小岛施了个“魔法”,规定矿工在小岛上只能正南正北正西正东走。也就是说矿工不能斜着在岛上走。
这个小岛在一个二维直角坐标系中描述。
你的任务就是帮gameboy找一个建造基地的位置,使矿工能以最快的速度采完所有矿。
输入数据有多组。每组数据的第一行是一个正整数n(0<n<1000000),表示小岛上有n个金矿。在接下来的n行中,每行有两个实数x,y,表示其中一个金矿的坐标。n=0表示输入数据结束。
每一组输入数据对应一行输出,输出两个实数x,y(保留小数点后两位),也就是你找到的建造基地的位置坐标。如果坐标不唯一,可以任选一个输出。
感觉要用最短路...枚举?其实只要把横纵坐标排下序找中位数就行...T_T
//摘自一位大牛的博客 #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int MAXN=1000005; double a[MAXN],b[MAXN]; int main() { int i,n; while(scanf("%d",&n),n) { for(i=0;i<n;i++) scanf("%lf%lf",&a[i],&b[i]); sort(a,a+n); sort(b,b+n); printf("%.2lf %.2lf\n",a[n/2],b[n/2]); } return 0; }
T2-UVa11300-分金币(采完矿了分金币?)
大意就是n个人围成一个圈,每个人有一些金币,每个人给左右两边的人一些金币,使得最后每个人的金币数相等,求转手的金币的最小值(金币总数总是能整除n)
有多组数据,具体看这里:http://acm.hust.edu.cn/vjudge/problem/33899
首先,对于相邻的两个人来说(比如1和2),如果1给了2某些同时2也给了1某些,那么这一定不是最优的,所以相邻两个人之间的金币流转可以转换成单向的,设xn表示第x个人给了他左边的人xn个金币,此值可正可负(负数就代表他从左边的人那里获得了金币)
对于第一个人:A1(原有的金币)-x1+x2=M(平均数)=>x2=M-A1+x1=x1-C1(设C1=A1-M),以后的人也类似
所以xn=x1-C(n-1)
我们要求的是所有x的绝对值最小的情况
Cn可以递推得到,我们只要求得最优的x1即可
可以发现当x1是所有C值的中位数是最优(Tip:绝对值就是数轴上两点间的距离不是吗~~)
剩下的就很简单啦
1 #include<iostream> 2 #include<algorithm> 3 #include<cmath> 4 using namespace std; 5 const int maxn=1000000+10; 6 int N,M,A[maxn],C[maxn]; 7 int main() 8 { 9 long long sum; 10 while(cin>>N){ 11 sum=0; 12 for(int i=1;i<=N;i++) cin>>A[i],sum+=A[i]; 13 M=sum/N;C[0]=0; 14 for(int i=1;i<N;i++) C[i]=C[i-1]+A[i]-M; 15 sort(C,C+N); 16 long long pos=C[N/2],/*求得的中位数*/ans=0; 17 for(int i=0;i<N;i++) ans+=abs(pos-C[i]); 18 cout<<ans<<endl; 19 } 20 return 0; 21 }
标签:
原文地址:http://www.cnblogs.com/gzhonghui/p/5734138.html