加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

大神排队--输油管道问题--士兵站队-

(2018-09-17 11:21:51)
分类: 排序
一)395.大神排队(贪心排序)
现在共有n个同学要排成一列,每个同学有两个属性:影响力和承受能力。给一个同学造成的心理创伤指数,等于所有在他前面同学的影响力之和,减去他的承受能力。
请安排一下排队顺序,尽量使受到心理创伤最大的同学少受创伤。
输入格式:
第1行是整数n,表示同学人数
第2~n+1行,每行两个自然数,分别是该同学的影响力和承受能力。
输出格式:
输出1行1个整数,为你安排的顺序中受到心理创伤最大的同学受到的创伤

输入样例:
3
10 3
2 5
3
输出样例:
2

问题分析:
排序,关键确定逆序条件。
用冒泡去理解,假如前面已经完全排序完毕,第i,j两个人的排序比较是:
sum+a[j]-b[i] vs sum+a[i]-b[j];
a[i]+b[i]  vs   a[j]+b[j]
两值相等的话,谁的魅力a[i]小排前面
#include "bits/stdc++.h"
using namespace std;
int n;
struct demo{
    int x,y;
    } s[50050];
bool cmp(demo x,demo y)
{
    if(x.x+x.y < y.x+y.y) return 1;
    if(x.x+x.y > y.x+y.y) return 0;
    if(x.x < y.x) return 1;
    return 0;
     
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int x,y;cin>>x>>y;
        s[i].x=x;s[i].y=y;
        }
    sort(s+1,s+n+1,cmp);
    int tot=0,ans=-2100000;
    for(int i=1;i<=n;i++)
    {
        ans=max(ans,tot-s[i].y);
        tot +=s[i].x;
        }
    cout<<ans<<endl;   
    return 0;
     

二)ss2303输油管道问题
某石油公司计划建造一条由东向西的主输油管道。该管道要穿过一个有n 口油井的油田。从每口油井都要有一条输油管道沿最短路经(或南或北)与主管道相连。如果给定n口油井的位置,即它们的x 坐标(东西向)和y 坐标(南北向),应如何确定主管道的最优位置,即使各油井到主管道之间的输油管道长度总和最小的位置? 证明可规定时间内确定主管道的最优位置。
编程任务:
给定n 口油井的位置,编程计算各油井到主管道之间的输油管道最小长度总和。
输入
文件第一行是油井数n,1<=n<=10000。接下来n行是油井的位置,每行2个整数x和y,-10000<=x,y<=10000。
输出
输出油井到主管道之间的输油管道最小长度总和。
样例输入
5
1 2
2 2
1 3
3 -2
3 3
样例输出
6
var a:array[0..10000] of longint;
    x,i,t,n:longint;
 procedure qk(low,high:longint);
 var l,h,mid:longint;
 begin
  l:=low;h:=high;mid:=a[(l+h) div 2];
  repeat
   while (l<=high) and (a[l] < mid) do inc(l);
   while (h>=low)  and (a[h] > mid) do dec(h);
   if l<=h then
   begin
    a[0]:=a[l];
    a[l]:=a[h];
    a[h]:=a[0];
    inc(l);
    dec(h);
   end;
  until l > h;
  if l < high then qk(l,high);
  if h > low then qk(low,h);
 end;
begin
 readln(n);
 for i:=1 to n do readln(x,a[i]);
 qk(1,n);
 t:=0;x:=(1+n) div 2;
 for i:=1 to n do t:=t+abs(a[i]-a[x]);
 writeln(t);
end.

三)ss2299士兵站队
在一个划分成网格的操场上,n个士兵散乱地站在网格点上。网格点由整数坐标(x,y)表
示。士兵们可以沿网格边上、下、左、右移动一步,但在同一时刻任一网格点上只能有一名
士兵。按照军官的命令,士兵们要整齐地列成一个水平队列,即排列成
(x,y),(x+1,y),…,(x+n-1,y)。如何选择x 和y的值才能使士兵们以最少的总移动步数排成一列。
编程任务:
计算使所有士兵排成一行需要的最少移动步数。
输入
输入士兵数n,1<=n<=10000。接下来n 行是
士兵的初始位置,每行2 个整数x 和y,-10000<=x,y<=10000。
输出
输出的第1 行中的数是士兵排成一行需要的最少移动步数。
样例输入
5
1 2
2 2
1 3
3 -2
3 3
样例输出
8
type sj=array[1..10001]of longint;
var x,y:array[1..10001]of longint;
    i,mid,step,n,a,min:longint;
procedure px(l,r:longint; var y:sj);
var i,j,m,t:longint;
begin
    i:=l; j:=r; m:=y[(l+r)div 2];
    repeat
     while y[i] < m do inc(i);
     while y[j] > m do dec(j);
     if i <= j then
      begin
        t:=y[i]; y[i]:=y[j]; y[j]:=t;
            inc(i); dec(j);
      end;
    until i > j ;
    if l < j then px(l,j,y);
    if r > i then px(i,r,y);
end;
begin
    readln(n);
    for i:=1 to n do    read(x[i],y[i]);
    px(1,n,y);
    mid:=y[n div 2+1];
    step:=0;
    for i:=1 to n do     step:=step+abs(y[i]-mid);
    px(1,n,x);
    for i:=1 to n do     x[i]:=x[i]-i+1;
    px(1,n,x);
    mid:=x[n div 2+1];
    for i:=1 to n do     step:=step+abs(x[i]-mid);
    writeln(step);
end.

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有