《程序员》官方BLOG

欢迎热心的读者随时与我们交流,您的支持是我们最大的动力!

用户操作
[即时聊天] [发私信] [加为好友]
《程序员》编辑
最近评论
domemy:Linux 环境下的多核调试
— Intel + Totalview 强强联合!
目前,在软件开发行业,各种性能优异的调试工具层出不穷。但是,它们中的绝大部分都只支持windows环境。即使能支持linux平台,操作起来也很不方便。因此,对于长期在linux上编写程序的开发人员来说,如何调试就成了一个令人头痛的问题!Intel软件 和 Total……
apple_hufangqiaqia:教我们.net的老师也讲这本书蛮好的
cyferl:读完,了解到不少网路安全方面的知识!
zhouqd:很想了解软件工程的历史
elvishehai:呵呵
文章分类
收藏
    相册
    《程序员》08年封面秀
    06年《程序员》封面秀
    07年《程序员》封面秀
    Logo
    编辑部合影
    调查分析图表
    模版
    文章用图
    新年祝福,名家寄语
    友情链接
    博文视点
    杂志订阅
    杂志订阅
    征文启事
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 2008年06期算法擂台解答收藏

    新一篇: 记者手记:敏捷大会的收获 | 旧一篇: OpenAPI:是互联网的新机会,还是下一轮泡沫?

     
    支援救灾
    20085121428分,四川省发生强烈地震,震中位于阿坝州汶川县,地震造成了严重的生命和财产损失。中国人民解放军某部接上级命令,组织部分官兵,携带重要的救灾物品,尽快赶往灾区支援救灾。
    第一批赶赴灾区的官兵共有N人,每人都要先到军备库领取需携带的救灾物品,然后整装打包,再整队集合发出。现在每名官兵已拿到各自要携带的物品清单,由于清单内容不同,他们在军备库领取物品所需的时间也不同,整装打包的时间也不同。
    军备库有两名管理员负责发放物品,为了能够尽快整队出发,官兵们将排成两条队伍,分别在两名管理员处领取物品。每名官兵在领到物品后,马上整装打包,打完包后马上到指定地点集合。已知每名官兵领取物品和整装打包的时间,请你安排一种最佳的分队和排队方案,使得部队能够尽快出发支援救灾。
    【输入】
    从键盘输入数据。第一行为正整数RR<=10),表示以下共有R组数据。然后分别是R组数据。
    每组数据的第一行为正整数N0<N<=200),以下有N行,每行两个正整数AiBi0<Ai, Bi<=200),分别代表第i名官兵领取物品和打包的时间。
    【输出】
    对于每组数据,单独一行输出一个整数T,代表从领取物品开始到所有官兵打包结束可整队集合的最短时间。
    样例:
     
    样例输入
    样例输出
    2
    2
    1 3
    3 2
    5
    2 2
    7 7
    1 3
    6 4
    8 5
    5
    17
     

    样例输入
    样例输出
    2
    2
    1 3
    3 2
    5
    2 2
    7 7
    1 3
    6 4
    8 5
    5
    17
     
    第二组数据的一种最佳方案如下:

    队伍1
    队伍2
    7 7
    6 4
    2 2
    1 3
    8 5
     
    #include <iostream>
     #include <algorithm>
    #include <utility>
    #include <map>
     using namespace std;
     struct AB {  int a, b;  // 领取物品和整理打包时间  
    bool operator < (const AB &r) const // 用于排序 
     {   return b > r.b;  } };
    int main() { 
     int R;   // 数据组数  
    cin >> R; 
     for (int i = 0; i < R; i++)
      { 
         int N;  // 官兵人数  
         AB data[200]; // A、B数据 
         cin >> N; 
         for (int j = 0; j < N; j++)   
        cin >> data[j].a >> data[j].b; 
        sort(data, data + N);  // 按b排序
         map<int, int> Que;  // <当前领取时间,两条队伍的最长完成时间>  
        Que[data[0].a] = data[0].a + data[0].b; // 分配第一个人入队   
        int totalA = data[0].a;    // 当前总的领物品时间   
        //Que[data[0].second] = Que[0];  
        for (int j = 1; j < N; j++) // 逐个分配到不同队伍中 
       {    map<int, int> newQue; // 新的队伍状态 
       for (map<int, int>::iterator it = Que.begin(); it != Que.end(); ++it) 
       // 对于当前所有可能的不同队伍状态  
       {
         // 方案一:加入Que中    
        int oldTA = it->first;   // 当前队伍领取物品总时间 
        int oldSumTime = it->second; // 当前两条队伍的最长完成时间 
        int newSumTime = oldTA + data[j].a + data[j].b; // 新加入者的完成时间 
        if (newSumTime < oldSumTime) 
        newSumTime = oldSumTime; // 新的最长完成时间  
        // 要计算相同状态的最优值,即相同领取物品时间下的最短完成时间 
        map<int, int>::iterator it2 = newQue.find(oldTA + data[j].a);  
        if (it2 == newQue.end() || it2->second > newSumTime) // 无值或原值较大 
          newQue[oldTA + data[j].a] = newSumTime;  // 更新
        // 方案二:加入另一队伍中  
       oldTA = totalA - it->first;  //当前队伍领取物品总时间可计算得到  
       newSumTime = oldTA + data[j].a + data[j].b;     
      if (newSumTime < oldSumTime)      
        newSumTime = oldSumTime;   
      it2 = newQue.find(it->first);    
      if (it2 == newQue.end() || it2->second > newSumTime)   
       newQue[it->first] = newSumTime; 
       }    // 准备下一次循环  
      totalA += data[j].a; 
            // 更新总的领物品时间    Que.swap(newQue);    // 更新队伍状态   
    }
      int minTime = 200 * 200;   
      for (map<int, int>::iterator it = Que.begin(); it != Que.end(); ++it)  
      if (it->second < minTime)   minTime = it->second;
      cout << minTime << endl;  } 
      return 0;
     }

    发表于 @ 2008年06月20日 20:08:00|评论(loading...)|收藏

    新一篇: 记者手记:敏捷大会的收获 | 旧一篇: OpenAPI:是互联网的新机会,还是下一轮泡沫?

    评论

    #wangjizhou4 发表于2008-06-21 10:50:20  IP: 123.123.172.*
    怎么觉得有点不对劲?应该是R组数据,怎么只有一个输出?
    试了一组数据
    1
    20
    152 108
    101 162
    177 89
    172 116
    188 44
    72 8
    59 66
    79 30
    44 170
    187 170
    109 9
    121 192
    180 116
    174 141
    199 66
    116 48
    1 200
    124 200
    85 145
    52 122
    201
    答案是不是小了点 ??
    今天有事要出去,等晚上回来在仔细的读读程序
    #wangjizhou4 发表于2008-06-23 14:23:19  IP: 219.237.253.*
    读了代码才发现
    // 更新总的领物品时间 Que.swap(newQue); // 更新队伍状态
    这里被注释掉了
    #genedor 发表于2008-06-29 12:14:32  IP: 58.18.167.*
    看不懂。。。。
    #handsame3 发表于2008-07-01 17:23:43  IP: 220.250.1.*
    希望程序员网站,能够搞一个OnLineJundge的系统,有利于大家水平的提高。
    #yujunlong2000 发表于2008-07-10 09:12:55  IP: 218.108.1.*
    用上面的代码测试样例,结果都不正确
    其实就算是加上Que.swap(newQue);
    我想应该也不会正确的,其本身的思路就有问题.
    这是我的代码,结果保证是正确的,但效率可能还不是最优,STL近期才学的,希望高手多多指教.
    #include <windows.h>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <list>

    using namespace std;

    //模型搭建
    /*--------------------------------------------------------------
    * 由两个整数组成的数据类型为 T = {int a, int b}
    * 由N个T组成的数列 S = que[N]
    * 目标:把S分成S1[N1]和S2[N2](N1 + N2 = N),Snseq为Sn(n = 1, 2)的Nn个T的一种排序。
    * 设对于某一具体Snseq,Lnseq = max(sum(Snseq[k].a}(0<=k<i) + snseq[k])(0<i<Nn)
    * 注::sum(f(k)(g(k)))为满足g(k)条件的所有f(k)之和
    * 对于所有Snseq,Ln = min(Lnseq),L = max(L1, L2)
    * 最终目标:求改变S1[N1]和S2[N2] 使L最小时,L的值
    --------------------------------------------------------------*/

    //分析问题
    /*--------------------------------------------------------------
    * 1:Ln的值只需要对Sn[Nn]对Sn.b由大到小排序的Lnseq
    * 2:最终结果2L<sum(S.a)+max1(s.b)+max2(s.b)
    * 注::max1(s.b)+max2(s.b)为所有b中最大的两个的和
    * 3:最终结果2L>sum(S.a)+min1(s.b)+min2(s.b)
    --------------------------------------------------------------*/

    struct T{
    T(){};
    T(int ai, int bi) : a(ai), b(bi){};
    int a;
    int b;
    };

    typedef vector<T> QUE;

    inline bool compT(T a, T b)
    {
    return (a.b < b.b) ? false : true;
    }

    inline bool MaxT(T a, T b)
    {
    return (a.a + a.b &l
    #yujunlong2000 发表于2008-07-10 09:15:18  IP: 218.108.1.*
    inline bool MaxT(T a, T b)
    {
    return (a.a + a.b < b.a + b.b) ? true : false;
    }

    inline T AddOne(T *a, T *b)
    {
    T temp;
    temp.a = a->a + b->a;
    temp.b = (a->b < temp.a + b->b) ? (temp.a + b->b) : a->b;
    return temp;
    }

    //接收录入
    void Getsource(int R, list<int> *sourceN, list<QUE> *sourceque);
    //排序,并去掉结尾的小段,并得到最小可能值
    void Sortsource(int &N, vector<T> &que, int *top, int *bot);
    //迭代获得实际最小值
    int GetMin(T left, T right, int local);

    //void PrintSort(int R, list<int> *sourceN, list<QUE> *sourceque);

    int top, bot, N;
    vector<T> *que;

    void main()
    {
    int R, i;

    cin>>R;
    list<int> sourceN(R);
    list<QUE> sourceque(R);

    Getsource(R, &sourceN, &sourceque);

    list<int>::iterator qnowN = sourceN.begin();
    list<QUE>::iterator qnowque = sourceque.begin();
    for(i=0; i<R; i++)
    {
    Sortsource(*qnowN, *qnowque, &top, &bot);
    N = *qnowN;
    que = &(*qnowque);

    GetMin(T((*qnowque)[0].a, (*qnowque)[0].a + (*qnowque)[0].b), T(0, 0), 1);

    cout<<top<<endl;

    qnowque++;
    qnowN++;
    }
    //cout<<top<<endl<<bot<<endl;
    //PrintSort(R, &sourceN, &sourceque);
    system("pause");
    }
    #yujunlong2000 发表于2008-07-10 09:16:12  IP: 218.108.1.*
    int GetMin(T left, T right, int local)
    {
    if(local == N)
    {
    if(left.b < top && right.b < top) //小于以前的最小值
    top = (left.b < right.b) ? right.b : left.b; //更新最小值
    if(top == bot)
    //找到最小值
    return 1; //等于最小可能值,返回1
    return 0;
    }
    if(left.b >= right.b) //控制迭代方向,先加在长的队列上
    {
    if(left.b > top) //大于以前的最小值
    return 0;
    else
    {
    if(1 == GetMin(AddOne(&left, &(*que)[local]), right, local + 1)) //下一级
    return 1;
    if(1 == GetMin(left, AddOne(&right, &(*que)[local]), local + 1)) //下一级
    return 1;
    return 0;
    }
    }
    else
    {
    if(right.b > top)
    return 0;
    else
    {
    if(1 == GetMin(left, AddOne(&right, &(*que)[local]), local + 1))
    return 1;
    if(1 == GetMin(AddOne(&left, &(*que)[local]), right, local + 1))
    return 1;
    return 0;
    }
    }
    }

    void Sortsource(int &N, vector<T> &que, int *top, int *bot)
    {
    int i;
    int temptop, tempbot, tempN;
    vector<T>::iterator qT;
    //按b排序
    sort(que.begin(), que.end(), compT);
    //去掉尾巴
    qT = que.begin();
    for(i=0, temptop=tempbot=0; i<N; i++)
    {
    tempbot += qT->a;
    if(tempbot+qT->b > temptop)
    {
    temptop = tempbot+qT->b;
    tempN
    #yujunlong2000 发表于2008-07-10 09:17:22  IP: 218.108.1.*
    void Sortsource(int &N, vector<T> &que, int *top, int *bot)
    {
    int i;
    int temptop, tempbot, tempN;
    vector<T>::iterator qT;
    //按b排序
    sort(que.begin(), que.end(), compT);
    //去掉尾巴
    qT = que.begin();
    for(i=0, temptop=tempbot=0; i<N; i++)
    {
    tempbot += qT->a;
    if(tempbot+qT->b > temptop)
    {
    temptop = tempbot+qT->b;
    tempN = i;
    }
    qT++;
    }
    N = tempN + 1;
    que.resize(tempN + 1);
    if(N > 1)
    {
    *bot = (temptop + que[que.size() - 2].b - 1)/2 + 1;

    qT = min_element(que.begin(), que.end(), MaxT);
    *top = (tempbot + que[0].b + que[1].b + qT->a + qT->b + 1)/2;
    }
    else
    *top = *bot = temptop;
    }

    void Getsource(int R, list<int> *sourceN, list<QUE> *sourceque)
    {
    int i, j;
    vector<T>::iterator qnowT;
    list<int>::iterator qnowN = sourceN->begin();
    list<QUE>::iterator qnowque = sourceque->begin();
    for(i=0;i<R;i++)
    {
    cin>>*qnowN;
    *qnowque = QUE(*qnowN);
    qnowT = qnowque->begin();
    for(j=0;j<*qnowN;j++)
    {
    cin>>qnowT->a;
    cin>>qnowT->b;
    qnowT++;
    }
    qnowque++;
    qnowN++;
    }
    }
    #yujunlong2000 发表于2008-07-10 09:34:08  IP: 218.108.1.*
    问题可以先简化为只有一组数排队的情况,也就是假设每个人的整装打包时间都为0,要求时间最短:
    问题:有N块石头,重量为随意值(假设都以整数计算),要求把石头分成M堆(M=2),使每一堆的石头的总的重量为最小,也就是重的一堆的重量为最小.(M=2时可以得到较优算法,但M>2时还没有较优的算法,希望有兴趣的朋友与我联系:)电话:15824130996,邮箱:yujunlong2000@yahoo.com.cn,QQ:124888828
    #gwz005 发表于2008-10-05 21:01:19  IP: 122.139.48.*
    sort_by_c(a[i],p);
    depart(a[i],p);
    sort_by_p(m,T0);
    sort_by_p(n,T1);
    t1= get_time (m,T0);
    t2= get_time (n,T1);
    if(t1>t2)
    printf("the team%d's Mintime is%ld\n",i+1,t1);
    else
    printf("the team%d's Mintime is%ld\n",i+1,t2);
    }
    system("pause");
    }

    void sort_by_c(int l,struct Soldier q[])
    {
    int i,j,k;
    struct Soldier t;
    for(i=0;i<l-1;i++){
    k=i;
    for(j=i+1;j<l;j++){
    if(q[j].catch>q[k].catch)
    k=j;
    if(k!=i){
    t=q[i];
    q[i]=q[k];
    q[k]=t;
    }
    }
    }
    }
    void sort_by_p(int l,struct Soldier q[])
    {
    int i,j,k;
    struct Soldier t;
    for(i=0;i<l-1;i++){
    k=i;
    for(j=i+1;j<n;j++){
    if(q[j].package>q[k].package)
    k=j;
    if(k!=l){
    t=q[i];
    q[i]=q[k];
    q[k]=t;
    }
    }
    }
    }
    void depart(int I,struct Soldier *q) {
    int j,team0=0,team1=0;
    m=0;n=0;
    for (j=0;j<I;j++,q++){
    if(team0<=team1){
    team0+=q->catch;
    T0[m]=*q;m++;
    }
    e
    #gwz005 发表于2008-10-05 21:03:58  IP: 122.139.48.*
    完整的不好意思发··太不完善,很业余··刚学C,本题就是为了课程设计,我做出来的一直被说占用内存太大··没办法·还不会用链表··想看的朋友QQ联系414643274
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © 《程序员》编辑