随笔 - 70  文章 - 160  trackbacks - 0

公告:
知识共享许可协议
本博客采用知识共享署名 2.5 中国大陆许可协议进行许可。本博客版权归作者所有,欢迎转载,但未经作者同意不得随机删除文章任何内容,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言。

常用链接

留言簿(8)

随笔档案

文章档案

搜索

  •  

积分与排名

  • 积分 - 177880
  • 排名 - 147

最新评论

阅读排行榜

评论排行榜


原文链接:

http://www.wutianqi.com/?p=1181


 

大家在学习C++编程时,一般在输入方面都是使用的cin.
而cin是使用空白(空格,制表符和换行符)来定字符串的界的。
这就导致了对于带有空格的字符串,比如”I Love www.CppLeyuan.com”
只能读入”I”,后面的都无法读入。
这时怎么办?

 一.对于字符数组
方法一:getline()
读入整行数据,它使用回车键输入的换行符来确定输入结尾。
调用方法: cin.getline(str, len);
第一个参数str是用来存储输入行的数组名称,第二个参数len是要读取的字符数。

 

 1 #include <iostream>
 2 using namespace std;
 3  
 4 int main()
 5 {
 6     char str[30];
 7     cin.getline(str, 30);
 8     cout << str << endl;
 9     return 0;
10 }

 

 

 

方法二:get()

调用方法:cin.get(str, len);

 

 1 #include <iostream>
 2 using namespace std;
 3  
 4 int main()
 5 {
 6     char str[30];
 7     cin.get(str, 30);
 8     cout << str << endl;
 9     return 0;
10 }

 

 

 

那么两者有何区别?
两者都读取一行输入,直至换行符。
然后,getline将丢弃换行符,而get()将换行符保留在输入序列里
所以,再使用cin.get()输入多行数据时,中间可以使用get()消除换行符。

 

 

 

 1 #include <iostream>
 2 using namespace std;
 3  
 4 int main()
 5 {
 6     char str1[30], str2[30];
 7     cin.get(str1, 30);
 8     cin.get();
 9     cin.get(str2, 30);
10     cout << "str1: " << str1 << endl;
11     cout << "str2: " << str2 << endl;
12     return 0;
13 }

 

 

 

因为get(str, len)和get()都是cin的类成员,所以可以合并起来写:

 

 1 #include <iostream>
 2 using namespace std;
 3  
 4 int main()
 5 {
 6     char str1[30], str2[30];
 7     cin.get(str1, 30).get();   // 注意这里!
 8     cin.get(str2, 30);
 9     cout << "str1: " << str1 << endl;
10     cout << "str2: " << str2 << endl;
11     return 0;
12 }

 

 

 

 

(欢迎大家去我论坛学习:C++奋斗乐园http://www.cppleyuan.com/)

二.对于string类
方法一:getline(cin, str)

这说明这里的getline不是类方法。

 

 

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4  
 5 int main()
 6 {
 7     string str;
 8     getline(cin, str);
 9     cout << str << endl;
10     return 0;
11 }

 

 

PS:以后如果对输入方面还有更多了解,会继续补充,希望大家支持,多多交流。

posted @ 2010-08-31 11:05 Tanky Woo 阅读(3984) | 评论 (2)编辑 收藏

原创链接:http://www.wutianqi.com/?p=1162



上次论坛里一个会员问的。
感觉这个程序作为DFS入门是很理想的,大家应该都能看懂。
贴出来和大家分享:

 

 1#include<iostream>
 2using namespace std;
 3int a[100= {0};
 4int n;
 5int count=0
 6void dfs(int k)
 7{
 8   if(k >= n)
 9   {
10      for(int i = 0;i < n;i++)
11      {
12         cout<<a[i]<<" ";
13      }

14      count++;
15      cout<<endl;
16   }
     
17   else
18   {
19      for(int i = 1;i <= n;i++)
20      {
21         a[k] = i; 
22         dfs(k + 1);        
23      }
       
24   }
    
25}

26int main()
27{
28   while(cin>>n)
29   {
30      count=0;
31      int k = 0;
32      dfs(k);  
33      cout<<count<<endl;             
34   }
    
35}
posted @ 2010-08-30 19:59 Tanky Woo 阅读(1186) | 评论 (1)编辑 收藏
 



http://www.wutianqi.com/?p=1157



集合A的幂集是由集合A的所有子集所组成的的集合。

 

如:A={1,2,3},则A的幂集P(A)={{1,2,3},{1,2},{1,3},{1},{2,3},{2},{3},{ }}。

求一个集合的幂集就是求一个集合的所有的子集,方法有穷举法,分治法,回溯等,这里主要介绍一下回溯法

回溯法是设计递归过程的一种重要的方法,它的求解过实质上是一个先序遍历一棵“状态树”的过程,只是这棵树不是遍历前预先建立的,而是隐含在遍历过程中的。

幂集中的每个元素是一个集合,它或是空集,或含集合A中一个元素,或含集合A中两个元素…… 或等于集合A。反之,从集合A 的每个元素来看,它只有两种状态:它或属幂集的无素集,或不属幂集的元素集。则求幂集p(A)的元素的过程可看成是依次对集合A中元素进行“取”或“舍”的过程,并且可以用一棵二叉树来表示过程中幂集元素的状态变化过程,树中的根结点表示幂集元素的初始状态(空集);叶子结点表示它的终结状态,而第i层的分支结点,则表示已对集合A中前i-1个元素进行了取舍处理的当前状态(左分支表示取,右分支表示舍 )。因此求幂集元素的过程即为先序遍历这棵状态树的过程。

具体算法如下:

C/C++描述:

 1#include <iostream>
 2#include <cstring>
 3#include <ctype.h>
 4#include <stdlib.h>
 5#include <string>
 6using namespace std;
 7 
 8char a[100];
 9char b[100];
10 
11void GetPowerSet(int i, char a[])
12{
13    char x;
14    int k;
15    int len = strlen(a);
16    if(i >= len)
17    {
18        if(b[0])
19            cout << b <<  endl;
20        else
21            cout << "XX" << endl;  // 表示空集
22    }

23    else
24    {
25        x = a[i];
26        k = strlen(b);
27        b[k] = x;
28        GetPowerSet(i+1, a);
29        b[k] = 0;
30        GetPowerSet(i+1, a);
31    }

32}

33 
34 
35int main()
36{
37    while(scanf("%s", a) != EOF)
38    {
39        printf("%s的幂集是:\n", a);
40        printf("------------\n");
41        GetPowerSet(0, a);
42        printf("------------\n");
43    }

44}
posted @ 2010-08-30 19:45 Tanky Woo 阅读(3914) | 评论 (0)编辑 收藏
     摘要: 原帖地址:http://www.wutianqi.com/?p=1081   以下是我从网上收集的关于组合博弈的资料汇总: 有一种很有意思的游戏,就是有物体若干堆,可以是火柴棍或是围棋子等等均可。两个人轮流从堆中取物体若干,规定最后取光物体者取胜。这是我国民间很古老的一个游戏,别看这游戏极其简单,却蕴含着深刻的数学原理。下面我们来分析一下要如何才能够取胜。 (一)巴什博奕(B...  阅读全文
posted @ 2010-08-20 13:09 Tanky Woo 阅读(1790) | 评论 (0)编辑 收藏

原文链接:
http://www.wutianqi.com/?p=1028



          今天看了rakerichard的一篇文章,是写的看了《疯狂的程序员》后的一点感想。

 

          回忆起以前我看这本书,联系自己学编程这一年多,感触颇多。记得这本书刚出来时,我就在中关村图书大厦买了一本。至今已经快一年了。故事情节依稀记得一点。

          里面讲到了BOSS 绝的奋斗史,读大学时和寝室一伙人到处折腾,给别人装机子,去小公司找工作,以及后来的作为招聘人员去自己学校招员工,私下接外挂破解,和女友的坎坷经历直到最后的分手。

          绝影的人生并不好走,虽然大学还未毕业就找到工作了,但是可以看出他的艰辛,经常熬夜赶项目;节假日不能陪家人,结果女友也要求分手了。

          我不知道该说什么好,别人都说嫁人要嫁程序员,程序员只关心电脑,不会在外面过那种花花绿绿的生活,这是褒义,还是贬义?也许只有说这话的人心里才清楚。

          大学是读自动化的,连我都不知道我为何要报自动化,我只知道,高考没考到自己预想的分数,考了一个半吊子的分数:568分,而一本分数线是548.就这么高不高,低不低的。连我老爸当年读的中南财经政法大学都读不了,于是我也懒得管了,直接让我父母报,结果第一志愿是北京化工大学的机械工程及其自动化,第二志愿是北京化工大学的自动化。最后第一志愿没录取,于是我到了北化的自动化系。虽然读了两年大学,我还不知道我这个专业到底是干啥的,只知道这个专业是一个万金油,啥都行~~~

           大一刚进校,因为高考完在家天天玩网游,开学了还没回过神来,别人都忙于互相认识,一起游览北京的一些旅游景点,而我却忙于在网吧与寝室两地颠簸。那时刚开学,班级和学校有许多的活动,我一个都没参加,记得开学就有学校和院的各个部门招人手,我那时没认识到德育分的重要性,也没有刻意去培养自己的结交能力(不过我的朋友还是非常多的~~在学校,许多人都和我很熟悉,因为我个人性格是比较活泼开朗的,且喜欢开玩笑,所以都比较随和。),但学校又要求每人都得报2项,所以其中一项我没去,另外一项别人打电话过来了,我也说没时间~~~(是不是很拽?)其实也不是不给他们面子,只是在我眼中,我不喜欢这些权势及口头上的较量,靠嘴皮子进去,一点用都没,而且在我看来,这些东西都是无聊至极的,一群把自己当成官一样来看待的,让我感觉很不舒服。我喜欢那种靠自己真实实力较量的生活。并且在我看来,等工作了这些权势竞争的生活多的是,在大学去浪费时间花在这上面太不值得了。就这么浑浑噩噩的一个学期快过完了,临近寒假,发现别人虽然分一部分心思去弄学校各个部门的活,但是也确实培养了他们的个人能力,而我呢?除了会去网吧,还是去网吧。虽然那时成绩不差,在班级30人中还能排在第10名。但是自己缺乏了其他独特的能力。因为我接触计算机很早,是从小学5年级开始的,所以我想到了从计算机这方面发展,刚开始对编程一窍不通,买了基本PS,FLASH,DW的书看,结果自己就是在美术细胞上太过于匮乏,始终弄不好,就这样折腾了3个多月,最终放弃了,那时也知道了C语言,且知道下学期要学C语言,所以就提前自学了。我的编程生涯也就是从这个时候开始的(起步很晚~~)。

           刚开始学C语言,我就被吸引了,作为男生,我相信好多人都很YM那些开发软件的人,我也不例外,而接触了C语言,我才知道,这就是可以开发出软件的东东,于是,我埋头苦学…汗,其实也算不上苦学,就是把自己的课程都丢了,天天只看C语言的书,因为我不是计算机专业的,没人教我,也没人给我经验,我就只能靠自己,计算机编程这方面的书都很贵的,还好有父母的经济支持,这样算一算,我10个月在买书上就花了2000元。我到现在都不知道怎么花的,反正牛人的书我都买了,还订了好多杂志。记得看了谭老的《C语言程序》,《C Primer Plus》, 《The C Programming Language》 《C陷阱与缺陷》 《C专家编程》等等~~~太多了,我经常没去上课,一个人抱着书和电脑去图书馆学。结果自己专业没顾着,大二下学期还弄了个年级300人,倒数10几名~~

           大二上学期我报了等级考试的三级数据库,也顺利的一次通过。呵呵,现在想来,也没啥高兴的,毕竟那些都是虚的,只需要靠2本书死记就过的,没有一点技术含量,不值得高兴。到了现在,数据库的一些知识也快忘光了。

           大二上学期的暑假,我开始学习C++了。那时学了一段时间,寂寞了,于是建了几个QQ群,在网上召集了一批C++爱好者一起交流,也就是那个时候,有了创办一个论坛让大家一起交流学习的想法。也就是在大二下学期开学后,随着群的人越来越多,许多人也提议弄一个专门学习交流的地方,于是我买了空间和域名,办了一个论坛。因为我觉得人生就要奋斗,我们学习编程,何尝不是在为以后而奋斗,所以我给群,以及论坛取名叫C++奋斗乐园。域名我也选择了cppleyuan。

           最开始接触ACM不知道是在什么时候,应该实在大一下学期或大二上学期吧。那时就觉得这挺有趣的,但是也没买书学习算法,就这么直接找上了POJ,经常把题目看懂就花了1个小时,然后做不出来,再分析别人代码又是几个小时~~~汗…后来觉得这东西不是我这种人弄的,就放弃了。不过还好,只是暂时放弃,在大二下学期开学后1个月,也就是2010年4月份左右吧。我又开始搞ACM了,因为学习C和C++也有一段时间了,对于编程也有了一定的认识,不再是那个初入编程大门,懵懵懂懂乱学的人了,我买了刘如佳老师的《算法学习经典入门》,《算法艺术与信息学竞赛》,吴文虎老师的《世界大学生程序设计竞赛》以及算法的圣经—-《算法导论》。就这么开始一个人在算法的海洋里探索了。也就是这个时候,因为自己对这方面有了解,并且觉得论坛不能只搞C++方面,所以我把论坛一部分分给了算法。毕竟算法是程序的灵魂。但是POJ对于我这个刚起步的小菜来说还是难了些。所以我开始转向HDOJ了,7月10号注册的。今天是8月17号,已经刷了210道水题了。我感觉,每AC一道题目,就感觉自己快乐了一分。也许这就是算法的魅力把,也可能这就是男人喜欢对事物的绝对掌控,感觉自己学懂了这个算法,就感觉自己多了一项能力。

           假期我给论坛弄了C/C++小项目和ACM刷题活动。当时我还到处找资料,花了一下午为C/C++小项目的第一个写了一个详细的流程图,结果到最后无人问津,只有个别人做了,wujing的就做的很好,赞一个。不过还好,ACM刷题活动倒是很受欢迎,每天都有一批人和我一起刷,包括MiYu,大帅,萝莉,timest,ac-quest等等。当然,amb教主我就不多说了,我只能YM。小白就是专门和我竞争的家伙。。。最近被他赶超了10题。郁闷。不过假期确实还是很开心的。毕竟结交了一群志同道合的朋友。

          现在假期也快结束了,8月20号返校,还得搬校区。

         看的书很多,想的也很多。喜欢思考编程,思考人生哲理。平时除了编程的书,我就最喜欢看自然科学和人生哲理了,《当下的力量》,《遇见心想事成的自己》,《秘密》这些书都很好,教会了我很多道理。感觉这些书就和算法一样,讲的都是内涵。人生就像编程,编的是人生,让人生合理,规划好人生,人生才能成功。

           最后,我想感谢C++奋斗乐园的各位斑竹,感谢假期陪我刷题的哥们,感谢支持我的论坛会员们。Orz

         以上算是发泄自己的情感,也算是倾述自己的经历,或算是总结自己的经验。不求能给大家什么帮助,只求大家能一起多交流点自己的经验,互相借鉴,互相学习。
                                                                                                                                                                                                
                                                                                                                                                                          TankyWoo    
                                                                                                                                                                    2010年8月7号
我的博客:http://www.wutianqi.com/ 希望大家多多交流。

posted @ 2010-08-17 11:33 Tanky Woo 阅读(2232) | 评论 (25)编辑 收藏

The Sieve of Eratosthens
爱拉托逊斯筛选法


(原创链接:http://www.wutianqi.com/?p=264[2:23]
思想:对于不超过n的每个非负整数P,删除2*P, 3*P…,当处理

完所有数之后,还没有被删除的就是素数。

若用vis[i]==1表示已被删除,则代码如下:
—————————————————–
代码一:

1memset(vis, 0sizeof(vis));
2for(int i = 2; i <= 100; i++)
3    for(int j = i*2; j <= 100; j += i)
4        vis[j] = 1;


上面的代码效率已经很高了。
但还可以继续优化。
看一个改进的代码:
——————————————————
代码二:

 1int m = sqrt(double(n+0.5));
 2 
 3for(int i = 2; i <= m; i++)
 4    if(!vis[i])
 5    {
 6        prime[c++= i;
 7        for(int j = i*i; j <= n; j += i)
 8        {
 9            vis[j] = 1;
10        }

11    }



——————————————————
先分析代码一:
这个代码就是简单的将Eratosthenes筛选法描述出来。不用多说。
分析代码二:
考虑几点:
1.为何从i=2~m?
因为下面的j是从i*i开始的。
2.为何j从i*i开始?
因为首先在i=2时,偶数都已经被删除了。
其次,“对于不超过n的每个非负整数P”, P可以限定为素数,
为什么?
因为,在 i 执行到P时,P之前所有的数的倍数都已经被删除,若P

没有被删除,则P一定是素数。
而P的倍数中,只需看:
(p-4)*p, (p-2)*p, p*p, p*(p+2), p*(p+4)
(因为P为素数,所以为奇数,而偶数已被删除,不需要考虑p*(p

-1)等)(Tanky Woo的程序人生)
又因为(p-4)*p 已在 (p-4)的p倍中被删去,故只考虑:
p*p, p*(p+2)….即可
这也是i只需要从2到m的原因。
当然,上面 p*p, p*(p+2)…的前提是偶数都已经被删去,而代码

二若改成 j += 2*i ,则没有除去所有偶数,所以要想直接 加2*i

。只需在代码二中memset()后面加:
for(int i = 4; i <= n; i++)
if(i % 2 == 0)
vis[i] = 1;
这样,i只需从3开始,而j每次可以直接加 2*i.
------------------------------------------------------
这里用代码二给大家一个完整的代码:

 1//版本二
 2//Author: Tanky Woo
 3//Blog: www.wutianqi.com
 4 
 5#include <stdio.h>
 6#include <string.h>
 7#include <math.h>
 8int vis[100];
 9int prime[100];
10int c = 0;
11int n;
12int main()
13{
14    scanf("%d"&n);
15    int cnt = 1;
16 
17    memset(vis, 0sizeof(vis));
18    int m = sqrt(double(n+0.5));
19 
20    for(int i = 2; i <= m; i++)
21        if(!vis[i])
22        {
23            prime[c++= i;
24            for(int j = i*i; j <= n; j += i)
25            {
26                vis[j] = 1;
27                //printf("%d\n", j);
28            }

29        }

30 
31    for(int i = 2; i < n; i++)
32    {
33        if(vis[i] == 0)
34        {
35            printf("%d ", i);
36            cnt++;
37            if(cnt % 10 == 0)
38                printf("\n");
39        }

40    }

41    printf("\ncnt = %d\n", cnt);
42    return 0;
43}



完毕。


欢迎大家和我交流。(我的博客:http://www.wutianqi.com/)




posted @ 2010-08-04 13:55 Tanky Woo 阅读(1154) | 评论 (1)编辑 收藏
     摘要: 母函数(Generating function)详解 (因为我是用Word写好了贴上来的,不知为何图片点插入不管用,这是原文:http://www.wutianqi.com/?p=596,大家可以直接去这里看。) 前段时间写了一篇《背包之01背包、完全背包、多重背包详解》,看到支持的人很多,我不是大牛,只是一个和大家一样学习的人,写这些文章的目的只是为了一是希望让大家学的轻松,二是让自己复...  阅读全文
posted @ 2010-08-02 15:34 Tanky Woo 阅读(7154) | 评论 (8)编辑 收藏

背包之01背包、完全背包、多重背包详解

PS:大家觉得写得还过得去,就帮我顶博客,谢谢。

首先说下动态规划,动态规划这东西就和递归一样,只能找局部关系,若想全部列出来,是很难的,比如汉诺塔。你可以说先把除最后一层的其他所有层都移动到2,再把最后一层移动到3,最后再把其余的从2移动到3,这是一个直观的关系,但是想列举出来是很难的,也许当层数n=3时还可以模拟下,再大一些就不可能了,所以,诸如递归,动态规划之类的,不能细想,只能找局部关系。

1.汉诺塔图片

(引至杭电课件:DP最关键的就是状态,在DP时用到的数组时,也就是存储的每个状态的最优值,也就是记忆化搜索)

要了解背包,首先得清楚动态规划:

动态规划算法可分解成从先到后的4个步骤:

1. 描述一个最优解的结构;

2. 递归地定义最优解的值;

3. 以“自底向上”的方式计算最优解的值;

4. 从已计算的信息中构建出最优解的路径。

其中步骤1~3是动态规划求解问题的基础。如果题目只要求最优解的值,则步骤4可以省略。

背包的基本模型就是给你一个容量为V的背包

在一定的限制条件下放进最多(最少?)价值的东西

当前状态→ 以前状态

看了dd大牛的《背包九讲》(点击下载),迷糊中带着一丝清醒,这里我也总结下01背包,完全背包,多重背包这三者的使用和区别,部分会引用dd大牛的《背包九讲》,如果有错,欢迎指出。

(www.wutianqi.com留言即可)

首先我们把三种情况放在一起来看:

01背包(ZeroOnePack): 有N件物品和一个容量为V的背包。(每种物品均只有一件)第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

完全背包(CompletePack): 有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

多重背包(MultiplePack): 有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

比较三个题目,会发现不同点在于每种背包的数量,01背包是每种只有一件,完全背包是每种无限件,而多重背包是每种有限件。

——————————————————————————————————————————————————————————–:

01背包(ZeroOnePack): 有N件物品和一个容量为V的背包。(每种物品均只有一件)第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。

用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:

f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}

把这个过程理解下:在前i件物品放进容量v的背包时,

它有两种情况:

第一种是第i件不放进去,这时所得价值为:f[i-1][v]

第二种是第i件放进去,这时所得价值为:f[i-1][v-c[i]]+w[i]

(第二种是什么意思?就是如果第i件放进去,那么在容量v-c[i]里就要放进前i-1件物品)

最后比较第一种与第二种所得价值的大小,哪种相对大,f[i][v]的值就是哪种。

(这是基础,要理解!)

这里是用二位数组存储的,可以把空间优化,用一位数组存储。

用f[0..v]表示,f[v]表示把前i件物品放入容量为v的背包里得到的价值。把i从1~n(n件)循环后,最后f[v]表示所求最大值。

*这里f[v]就相当于二位数组的f[i][v]。那么,如何得到f[i-1][v]和f[i-1][v-c[i]]+w[i]?(重点!思考)
首先要知道,我们是通过i从1到n的循环来依次表示前i件物品存入的状态。即:for i=1..N
现在思考如何能在是f[v]表示当前状态是容量为v的背包所得价值,而又使f[v]和f[v-c[i]]+w[i]标签前一状态的价值?

逆序!

这就是关键!

1for i=1..N
2   for v=V..0
3        f[v]=max{f[v],f[v-c[i]]+w[i]};
4

分析上面的代码:当内循环是逆序时,就可以保证后一个f[v]和f[v-c[i]]+w[i]是前一状态的!
这里给大家一组测试数据:

测试数据:
10,3
3,4
4,5
5,6


这个图表画得很好,借此来分析:

C[v]从物品i=1开始,循环到物品3,期间,每次逆序得到容量v在前i件物品时可以得到的最大值。(请在草稿纸上自己画一画

这里以一道题目来具体看看:

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2602

代码在这里:http://www.wutianqi.com/?p=533

分析:


具体根据上面的解释以及我给出的代码分析。这题很基础,看懂上面的知识应该就会做了。

——————————————————————————————————————————————————————————–

完全背包:

完全背包(CompletePack): 有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

完全背包按其思路仍然可以用一个二维数组来写出:

f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k*c[i]<=v}

同样可以转换成一维数组来表示:

伪代码如下:

for i=1..N
    
for v=0..V
        f[v]
=max{f[v],f[v-c[i]]+w[i]}


顺序!

想必大家看出了和01背包的区别,这里的内循环是顺序的,而01背包是逆序的。
现在关键的是考虑:为何完全背包可以这么写?
在次我们先来回忆下,01背包逆序的原因?是为了是max中的两项是前一状态值,这就对了。
那么这里,我们顺序写,这里的max中的两项当然就是当前状态的值了,为何?
因为每种背包都是无限的。当我们把i从1到N循环时,f[v]表示容量为v在前i种背包时所得的价值,这里我们要添加的不是前一个背包,而是当前背包。所以我们要考虑的当然是当前状态。
这里同样给大家一道题目:

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1114

代码:http://www.wutianqi.com/?p=535

(分析代码也是学习算法的一种途径,有时并不一定要看算法分析,结合题目反而更容易理解。)

——————————————————————————————————————————————————————————–

多重背包

多重背包(MultiplePack): 有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

这题目和完全背包问题很类似。基本的方程只需将完全背包问题的方程略微一改即可,因为对于第i种物品有n[i]+1种策略:取0件,取1件……取n[i]件。令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值,则有状态转移方程:

f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k<=n[i]}

这里同样转换为01背包:

普通的转换对于数量较多时,则可能会超时,可以转换成二进制(暂时不了解,所以先不讲)

对于普通的。就是多了一个中间的循环,把j=0~bag[i],表示把第i中背包从取0件枚举到取bag[i]件。

给出一个例题:

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2191

代码:http://www.wutianqi.com/?p=537

因为限于个人的能力,我只能讲出个大概,请大家具体还是好好看看dd大牛的《背包九讲》。

暂时讲完后,随着以后更深入的了解,我会把资料继续完善,供大家一起学习探讨。(我的博客:www.wutianqi.com如果大家有问题或者资料里的内容有错误,可以留言给出,谢谢您的支持。)

原文下载地址:(Word版)
http://download.csdn.net/sour

个人原创,转载请注明本文链接:http://www.wutianqi.com/?p=539

posted @ 2010-07-31 19:07 Tanky Woo 阅读(18288) | 评论 (11)编辑 收藏

学校太让人失望了,居然连POJ都上不去了,还好今天ambition在我用百练AC掉这题后送来了另外一个POJ的网址,双喜临门,害我兴奋了半天,没有POJ的日子痛苦啊。毕竟题目来源还得靠它。

这是曾经没有AC掉的题目,不过在《程序设计导引及在线实践》上看过,看书写代码还是没亲自做的效果好。今天给假期题目来源找题,看中了这题,再次做,强化了一些基本功。

分析几点:

一。A~Z对应一个Hash数组

二。在每输入一个数据时就对数据进行处理,转换字母,去掉’-’

三。qsort的运行,具体看MSDN,这里就讲一点。

    一个是二位数组的qsort用法:

1
            2
            3
            4
            5
            6
            
 int compare( const void *arg1, const void *arg2 )
            {
            return strcmp((char*)arg1, (char*)arg2 );
            }
            int arr[n][11];
            qsort(arr, n, sizeof(arr[0]), compare);

  二是qsort的几个参数,这里一直不是记得很清楚。

1
            2
            3
            4
            5
            6
            
 void qsort(
            void *base,
            size_t num,
            size_t width,
            int (__cdecl *compare )(const void *, const void *)
            );

  注意:width: Element size in bytes

               cmp函数:如果是升序,则e1 > e2应返回1,e1 = e2 应返回0, e1 < e2 应返回-1.降序则相反。

直接发代码了:

时间有点大,是600多MS。

看见网上还有其他方法,大家可以去看看。

题目地址:

http://124.205.79.250/JudgeOnline/problem?id=1002

 

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            36
            37
            38
            39
            40
            41
            42
            43
            44
            45
            46
            47
            48
            49
            50
            51
            52
            53
            54
            55
            56
            57
            58
            59
            60
            61
            62
            63
            64
            65
            66
            67
            68
            69
            70
            71
            72
            73
            74
            
 // POJ 487-3279
            // Author: Tanky Woo
            #include <iostream>
            using namespace std;
             
            char hash[] = "22233344455566670778889990";
             
            char telphone[100001][20];
            char temp[20];
             
            int compare( const void *arg1, const void *arg2 )
            {
            return strcmp((char*)arg1, (char*)arg2 );
            }
             
            // www.wutianqi.com
            int main()
            {
            //freopen("input.txt", "r", stdin);
            int flag = 0;
            int nCases;
            scanf("%d", &nCases);
            for(int i = 0; i < nCases; ++i)
            {
            getchar();
            scanf("%s", telphone[i]);
            int len = strlen(telphone[i]);
            int t = 0;
            for(int j = 0; j < len; ++j)
            {
            if(telphone[i][j] >= 'A' && telphone[i][j] <= 'Z')
            temp[t++] = hash[telphone[i][j]-'A'];
            else if(telphone[i][j] >= '0' && telphone[i][j] <= '9')
            temp[t++] = telphone[i][j];
            else if(telphone[i][j] == '-')
            ;
            }
            strcpy(telphone[i], temp);
            }
             
            qsort(telphone, nCases, sizeof(telphone[0]), compare);
             
             
            for(int i = 0; i < nCases; ++i)
            {
             
            int cnt = 1;
            strcpy(temp, telphone[i]);
            int j;
            for(j = i+1; j < nCases; ++j)
            {
            if(strcmp(temp, telphone[j]) == 0)
            cnt++;
            else
            break;
            }
            if(cnt > 1)   //这个地方没处理好,麻烦。。。
            {
            flag = 1;
            for(int k = 0; k < 3; ++k)
            printf("%c", temp[k]);
            printf("-");
            for(int k = 3; k < 7; ++k)
            printf("%c", temp[k]);
            printf(" %d\n", cnt);
            }
            i = j-1;
            }
            if(flag == 0)
            printf("No duplicates.\n");
             
             
            return 0;
            }

欢迎您来到C++奋斗乐园,原创文章,转载请注明: 转载自Tanky Woo 的程序人生

文章标题: POJ 1002 487-3279

本文链接地址: http://www.wutianqi.com/?p=308

posted @ 2010-07-11 17:56 Tanky Woo 阅读(222) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2010-07-11 09:41 Tanky Woo 阅读(434) | 评论 (0)编辑 收藏
仅列出标题
共7页: 1 2 3 4 5 6 7