• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

kaikai向前走

转职任务完成。崭新fn诞生
  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

编程爱好者论坛第六次编程比赛题目

题目原文地址
http://www.programfan.com/club/showbbs.asp?id=126227

一、按要求编写以下函数。
功能:    将给定缓冲区中的#字符移到字符串尾部
函数名称:changetotail
入口参数:psztext指向字符缓冲区的指针,以0结尾。
出口:    psztext所指缓冲区中的#字符被移到缓冲区尾部
返回值:  在出口缓冲区中第一个#的位置,若缓冲区中无#字符则返回 -1

说明: 如传入("#W#W#W#WW#") 则传出时应转换为"WWWWW#####"并且返回值为 5
      如传入("1#2#3#")      则传出时应转换为"123###"并且返回值为 3


// 1
#include <stdio.h>

int changetotail(char *psztext)
{
    
const char *p = psztext;
    
char *p2 = psztext;
    
int ret;
    
    
if (p == NULL)
        
return -1;
    
    
while(*p2 = *p++)
        
*p2 != '#' && p2++;
    
    ret 
= p2 == --p ? -1 : p2 - psztext;
    
    
while(p2 < p)
        
*p2++ = '#';
    
    
return ret;
}

int main()
{
    
int i;
    
char s[][16] = 
    
{
        
"asdf#@",
        
"#@",
        
"###",
        
"",
        
"#D#D#D#D",
        
"D#D#D#D#D",
        
"#D#D#D#D#",
        
"D#D#D#D",
        
"######DDDD",
        
"DDDD######",
    }
;
    
for (i = 0; i < 10; i ++)
    
{
        printf(
"Case %d\n%s\n", i, s[i]);
        printf(
"%s\n%d\n", s[i], changetotail(s[i]));
    }

    
    
return 0;
}


第2题
二、任给 1<=n<=20 个不同的非零正整数,每个正整数最多使用1次,请问这n个正整数能够加和的结果共有多少种(不考虑和超出long的最大值的可以),
程序中请实现如下函数。用于计算数组data,中ncount的加和的数量。
long getsumcount(long data[], long count);
程序中可以出现别的辅助函数。或辅助结构等。

例如,
data[] = {1,2,3,4};
ncount = 4;
函数返回 10

分解如下。(0不算)

1  = 1
2  = 2
3  = 3 = 1+2
4  = 4 = 1+3

5  = 2+3 = 1+4
6  = 2+4 = 1+2+3
7  = 3+4 = 1+2+4
8  = 1+3+4
9  = 2+3+4
10 = 1+2+3+4
如上。所以结果是10种可能。

我的方法基本思想是把已经出现过的数字用一个位1来标记。避免做对一个数字是否存在的查找操作。
但long范围内要把所有的位都存下来,需要内存太大。2^32/8 byte = 512 MB
所以改为分段保存,连续的32768位存在一起。对连续32768个数字都没有出现过的情况则不记录这块数据
下面是我的程序:

// 2

#include 
<vector>
#include 
<algorithm>
using namespace std;
class Set
{
    typedef unsigned 
long Int;
    
struct bitSet // 存32768位
    {
        Int 
base; // 一个bitSet保留从base位开始的32768位标记
        Int buf[1024]; // 32*1024=32768位,这个大小其实是随意设的
        bitSet(Int b):base(b)
        
{
            memset(buf, 
0, sizeof(buf));
        }

        
void set(Int n)
        
{
            Int d 
= n - base;
            buf[d
>>5] |= 1 << (d & 0x1f); // 对第n位置位
        }

        
bool test(Int n) const
        
{
            Int d 
= n - base;
            
return (buf[d>>5] & (1 << (d & 0x1f))) != 0; // 判断第n位。
        }

        
struct Ptr // 这个是为了堆排序不用排bitSet对象(bitSet的体积比较大),排Ptr对象其实就是指针排序
        {
            Ptr(bitSet 
*pp = NULL):p(pp){}
            
bool operator < (const Ptr &o) const // 提供对bitSet的排序关系
            {
                
return p->base < o.p->base;
            }

            bitSet 
*p;
        }
;
    }
;
public:
    
~Set()
    
{
        
for (vector< bitSet::Ptr >::iterator b = bits.begin(); b != bits.end(); b++)
            delete b
->p; // 不要忘了释放空间
    }

    
void add(Int n)
    
{
        bitSet::Ptr bs 
= find(n);
        
if (bs.p == NULL) // 如果整个bitSet块都不存在,那么得添加一个新的块了
        {
            Int 
base = n & ~0x7fff;
            bs.p 
= new bitSet(base);
            bits.push_back(bs);
            push_heap(bits.begin(), bits.end());
        }

        
if (!bs.p->test(n)) // 如果这个位已经标记过,那么不应该添加到values内
        {
            bs.p
->set(n);
            values.push_back(n);
        }

    }

    
bool test(Int n)
    
{
        bitSet::Ptr bs 
= find(n);
        
if (bs.p == NULL)
            
return false;
        
return bs.p->test(n);
    }

    
const vector< Int > &getValues() const {return values;}
protected:
    bitSet::Ptr find(Int n) 
const
    
{
        typedef vector
< bitSet::Ptr >::size_type size_t;
        Int 
base = n & ~0x7fff;
        size_t d 
= 0;
        
const size_t size = bits.size();
        vector
< bitSet::Ptr >::const_iterator b = bits.begin(), e = bits.end();
        
while(d < size && b[d].p->base != base) // 最大堆查找算法。本来想stl内找,貌似没有,就人肉做一个了
        {
            
if (b[d].p->base < base)
                d 
= d*2 + 1;
            
else
                d 
= (d+1)*2;
        }

        
if (d >= size)
            
return bitSet::Ptr(); // 找不到返回NULL指针对象
        return b[d];
    }

    vector
< bitSet::Ptr > bits;
    vector
< Int > values;
}
;

long getsumcount(long data[], long count)
{
    Set 
set;
    
set.add(0); // 初始得有个0,便于下面代码统一
    for (int i = 0; i < count; i++)
    
{
        vector
< Set::Int >::const_iterator n;
        vector
< Set::Int > newInt;
        
const vector< Set::Int > &v = set.getValues();
        
for (n = v.begin(); n != v.end(); n++)
        
{
            
if (!set.test(*n + data[i])) // 对每个数字,如果加新数字的和不在集合内,那么准备添加到集合内
                newInt.push_back(*n + data[i]);// 之所以这里不直接添加到set内,是因为v就是set内的values,如果这里对set的values做增加元素,将导致迭代器n失效。
        }

        
for (n = newInt.begin(); n != newInt.end(); n++)
        
{
            
set.add(*n); // 把新的元素添加进去。
        }

    }

    
return set.getValues().size() - 1; // 最后去掉元素0
}

int main()
{
    
long data[] = 
    
{
        
0x1,0x2,0x4,0x8,
            
0x10,0x20,0x40,0x80,
            
0x100,0x200,0x400,0x800,
            
0x1000,0x2000,0x4000,0x8000,
            
0x10000,0x20000,0x40000,0x80000,
    }
;
    
    printf(
"%d\n", getsumcount(data, 20));

    
return 0;
}


posted on 2005-12-04 22:39  kaikai  阅读(1077)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3