免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3669 | 回复: 19
打印 上一主题 下一主题

竞赛题: 合并果子 etc.(做完一道 go on) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-11-07 00:43 |只看该作者 |倒序浏览
合并果子

【问题描述】
    在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。

    每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。

    因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。

    例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。

【输入文件】

    输入文件fruit.in包括两行,第一行是一个整数n(1<=n<=10000),表示果子的种类数。第二行包含n个整数,用空格分隔,第i个整数ai(1<=ai<=20000)是第i种果子的数目。

【输出文件】

    输出文件fruit.out包括一行,这一行只包含一个整数,也就是最小的体力耗费值。输入数据保证这个值小于231。

【样例输入】

3
1 2 9

【样例输出】

15

【数据规模】

对于30%的数据,保证有n<=1000:
对于50%的数据,保证有n<=5000;
对于全部的数据,保证有n<=10000。


go on~~~
本贴子不欢迎guan shui, 以及无聊者.

回复格式:
1. 程序
2. 可能的说明
3. 其它

[ 本帖最后由 yarco1 于 2005-11-7 00:54 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2005-11-07 01:06 |只看该作者
Huffman编码?

论坛徽章:
0
3 [报告]
发表于 2005-11-07 01:54 |只看该作者

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>

  4. #define MAX_BUF 1024

  5. void get_total(int*);
  6. int* get_numbers(const int);
  7. int cmp(const void*, const void*);

  8. int main()
  9. {
  10.         int n, i;
  11.         int *vector, *total;
  12.         int all = 0;
  13.        
  14.         //get total & numbers
  15.         get_total(&n);
  16.         vector = get_numbers(n);
  17.         n--;
  18.         total = (int*) malloc(sizeof(int)*n);
  19.         for(i=0; i<n; i++) {
  20.                 qsort(vector, n-i+1, sizeof(int), cmp);
  21.                 *(vector+n-i-1) += *(vector+n-i);
  22.                 *(total+i) = *(vector+n-i-1);
  23.         }
  24.        
  25.         //get total
  26.         for(i=0; i<n; i++)
  27.                 all += *(total+i);
  28.         printf("Total cost is: %dn", all);
  29.        
  30.         free(total);
  31.         free(vector);
  32.         return 0;
  33. }

  34. void get_total(int* n)
  35. {
  36.         printf("Get input: ");
  37.         scanf("%d", n);
  38.         getchar();  //jump over 'n'
  39. }

  40. int* get_numbers(const int total) //fuck, 还是这里处理输入麻烦
  41. {
  42.         char buf[MAX_BUF], *tmp;
  43.         int i = 1;
  44.         int* p;
  45.        
  46.         memset(buf, 0, MAX_BUF);
  47.         printf("Get each number of fruit:n");
  48.         fgets(buf, MAX_BUF-1, stdin);
  49.         p = (int*) malloc(total*sizeof(int));
  50.         tmp = strtok(buf, " ");
  51.         *p = atoi(tmp);
  52.         //printf("%dn", *p);exit(0);
  53.         while (i<total) {
  54.                 tmp = strtok(NULL, " ");
  55.                 *(p+i) = atoi(tmp);
  56.                 i++;
  57.         }
  58.         return p;
  59. }

  60. int cmp(const void* left, const void* right)
  61. {
  62.         const int* l = (const int*) left;
  63.         const int* r = (const int*) right;
  64.         return *l < *r;
  65. }
复制代码

论坛徽章:
0
4 [报告]
发表于 2005-11-07 01:59 |只看该作者

虫食算

靠, 这个明天做...

虫食算

【问题描述】
    所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:

       43#9865#045
    +    8468#6633
       44445506978

    其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5。

    现在,我们对问题做两个限制:

    首先,我们只考虑加法的虫食算。这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0。

    其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用相同的字母表示,不同的数字用不同的字母表示。如果这个算式是N进制的,我们就取英文字母表午的前N个大写字母来表示这个算式中的0到N-1这N个不同的数字:但是这N个字母并不一定顺序地代表0到N-1)。输入数据保证N个字母分别至少出现一次。

            BADC
      +    CRDA
            DCCC

    上面的算式是一个4进制的算式。很显然,我们只要让ABCD分别代表0123,便可以让这个式子成立了。你的任务是,对于给定的N进制加法算式,求出N个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解,

【输入文件】
    输入文件alpha.in包含4行。第一行有一个正整数N(N<=26),后面的3行每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这3个字符串左右两端都没有空格,从高位到低位,并且恰好有N位。

【输出文件】
    输出文件alpha.out包含一行。在这一行中,应当包含唯一的那组解。解是这样表示的:输出N个数字,分别表示A,B,C……所代表的数字,相邻的两个数字用一个空格隔开,不能有多余的空格。

【样例输入】
5
ABCED
BDACE
EBBAA

【样例输出】
1 0 3 4 2

【数据规模】
对于30%的数据,保证有N<=10;
对于50%的数据,保证有N<=15;
对于全部的数据,保证有N<=26。

论坛徽章:
0
5 [报告]
发表于 2005-11-07 02:09 |只看该作者
...数据规模...什么意思...
有更好的想法...发欧....
goon go on`

论坛徽章:
0
6 [报告]
发表于 2005-11-07 09:05 |只看该作者
第一题用qsort不好,当源数据基本是排好序的时候,qsort是效率是最低的
建议用二叉树

[ 本帖最后由 yzc2002 于 2005-11-7 09:15 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2005-11-07 11:02 |只看该作者
楼上的, qing教了. 您贴个代码吧...
当源数据基本是排好序的时候

这什么意思?没排好吧...什么是基本排好序了?

强烈希望楼上的贴代码

论坛徽章:
0
8 [报告]
发表于 2005-11-08 09:01 |只看该作者
原帖由 yarco1 于 2005-11-7 11:02 发表
楼上的, qing教了. 您贴个代码吧...

这什么意思?没排好吧...什么是基本排好序了?

强烈希望楼上的贴代码
        for(i=0; i<n; i++) {
                qsort(vector, n-i+1, sizeof(int), cmp);
                *(vector+n-i-1) += *(vector+n-i);
                *(total+i) = *(vector+n-i-1);
        }

第一次循环当然是没排过序的,但以后呢?除了最后一个数,其它都是从大到小排序的
用C++来表达,不费吹灰之力

  1. #include <iostream>
  2. #include <set>
  3. using namespace std;

  4. int main()
  5. {
  6.     multiset<int> val;
  7.     int num, x, y;
  8.     long long total;

  9.     cin >> num;
  10.     for(int i=0; i< num; i++)
  11.     {
  12.         cin >> x;
  13.         val.insert(x);
  14.     }

  15.     total = 0;
  16.     multiset<int>::iterator itr;
  17.     while(val.size() > 1)
  18.     {
  19.         itr = val.begin();
  20.         x = *itr;
  21.         val.erase(itr);
  22.         itr = val.begin();
  23.         y = *itr;
  24.         val.erase(itr);
  25.         total += x + y;
  26.         val.insert(x+y);
  27.     }
  28.     cout << total << endl;
  29. }
复制代码

set在STL里是用红黑树表示的

[ 本帖最后由 yzc2002 于 2005-11-8 13:30 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2005-11-08 12:56 |只看该作者
谢了, 明白了.

对了...那个set...
不能放相同数字的吧?

论坛徽章:
0
10 [报告]
发表于 2005-11-08 13:20 |只看该作者
原帖由 yarco1 于 2005-11-8 12:56 发表
谢了, 明白了.

对了...那个set...
不能放相同数字的吧?

那就改成用multiset
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP