﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-ACM征途-文章分类-转载</title><link>http://www.cppblog.com/Onway/category/12318.html</link><description>菜鸟级</description><language>zh-cn</language><lastBuildDate>Fri, 02 Sep 2011 01:00:02 GMT</lastBuildDate><pubDate>Fri, 02 Sep 2011 01:00:02 GMT</pubDate><ttl>60</ttl><item><title>基于X的GNOME、GTK、GDK、XLib、GLib等之间的关系(转)</title><link>http://www.cppblog.com/Onway/articles/154198.html</link><dc:creator>Onway</dc:creator><author>Onway</author><pubDate>Wed, 24 Aug 2011 02:26:00 GMT</pubDate><guid>http://www.cppblog.com/Onway/articles/154198.html</guid><wfw:comment>http://www.cppblog.com/Onway/comments/154198.html</wfw:comment><comments>http://www.cppblog.com/Onway/articles/154198.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Onway/comments/commentRss/154198.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Onway/services/trackbacks/154198.html</trackback:ping><description><![CDATA[<div><div>基于X的GNOME、GTK、GDK、XLib、GLib等之间的关系</div><div>(转自http://blog.chinaunix.net/space.php?uid=20334226&amp;do=blog&amp;id=1965083)</div><div></div><div>什么是Xlib?</div><div>The X Library是X Window程式最低阶的API，如果拿来和Windows比较起来，Xlib就和Windows APIs(或称Windows SDK)一样，算是最接近X Server的程序设计介面，它只提供最基本的绘图和讯息事件的处理。</div><div>什么是Xt?(X Toolkit Intrinsics)&nbsp;</div><div>Xt是第一个把Xlib包装成更抽象化的函式库，它提供了「物件导向」的程式设计架构，并且引进了一种称为「widget」的概念，这种「widget」资料结构也就是所谓的「User Interface Componets」像是menus、buttons或是TextBox等widgets。 从此以后程式设计师就可以用widget的观念，来架构我们的应用程式，让程式变得简单且容易了解。&nbsp;</div><div>不过Xt只定义了应用程式要如何和这些widgets沟通，并没有规定这些widgets的外观要长什么模样。 这些widgets真正的样子最后还是得靠更高层的函式库来处理。 (通常提供widgets的函式库，我们就称之为GUI Toolkit（X ToolKits)。&nbsp;</div><div>Motif、OpenLook和Lesstif等便都是从Xt Library衍生而来的图形介面函式库</div><div>Motif&nbsp;</div><div>Motif为目前最主要的GUI Toolkit，它便是以Xt的widget概念为基础，提供外观和Microsoft Windows 95极为类似的图形介面。 Motif是由Open Group (以前叫Open Software Foundation)所出产。&nbsp;</div><div>不过现在的Motif已经不只是单纯的GUI Toolkit了，它也包含了一个Motif window manager(窗口管理器)用来管理X Clients (X Applications)。</div><div></div><div>&nbsp;</div><div>什么是GDK?&nbsp;</div><div>GDK是标准Xlib函数调用的一个基本封装(wrapper),如果你对Xlib很熟悉,就不需要来重新熟悉绝大多数的GDK函数.所有的函数都是为了提供一 个方便直观的风格来访问Xlib函数库.另外,自从GDK使用GLib,在多平台上使用时,GDK变得更加的方便和安全.&nbsp;</div><div></div><div>什么是GLib?&nbsp;</div><div>GLib库提供了一系列函数(functions)和定义(definitions),在设计GDK和GTK程序时很有用.它提供了一些标准c函数库(stan dard libc)的替代函数,比如malloc,但在其他的系统上使用时有很多问题.&nbsp;</div><div></div><div>什么是GTK+?&nbsp;</div><div>GTK+是一个小型而高效的控件库,具有Motif的外观和风格.实际上,它比Motif看起来好多了,它包含有基本的控件和一些很复杂的的控件:例如文件选择、控件和颜色选择控件. GTK+提供了一些独特的特性,(至少,我知道其他的控件库不提供他们),例如,按钮不提供标签,它包含了一个子控件,在很多的时候是一个标签,但是,这个子控件也可以是一个映射,图像或者任何其他的程序员想要的集合.在整个的库中,你随处可见这种伸缩性.&nbsp;</div><div>Gnome的开发基础结构是围绕一组函数库的，所有的内容都是用可移植的ANSI C语言写成的，可以用于所有类UNIX系统，与图形相关的函数库依赖于X Window系统。 Gnome函数库是最高层的。 GTK＋由两部分组成，GTK和GDK。 GTK层为C语言提供了一个对象模型，并为UI工具包提供了最基本的widget，它是上层GUI派生的基础。 GTK是依赖于GDK的，GDK是Xlib的一个底层包装，Xlib库直接与X服务器对话。 除了&#8203;&#8203;Xlib以外的任何部分都是基于GLib的，它是一个有用的C函数库，提供了很多实用程序和可移植的功能以及一组容易被C语言使用的容器。&nbsp;</div><div></div><div>一个Gnome程序是使用多个库组成的层次结构：</div><div>GNOME (GNU Network Object Model Environment)是以GTK为基础的图形介面函式库。 和KDE一样，GNOME也是以建立一个完整、友善的图形使用环境为目标，并提供GNOME相关的软体。&nbsp;</div><div>Gnome库在最高层，包括帮助例程，类和特殊的widget，并为应用程序提供一个基础架构。&nbsp;</div><div>第二层是GTK，它是GTK＋库的一部分。 这个库提供了基本的工具包和widget来创建GUI应用程序。 大多数GUI是直接用GTK编写的。 GTK同时为Gnome库提供了一个功能强大的对象系统。&nbsp;</div><div>再下一层是GDK，它简单的对X函数库进行了包装，只有在我们进行特殊绘画或设置窗口的特殊属性的时候才会用到它.&nbsp;</div><div>最下面一层是Glib，它是C的一个实用程序库，包括可移植性和一些实用程序功能，以及一些容器类，例如：链表，可变数组，变长字符串，HASH西表），缓存，一个事件循环和其他有用的结构。&nbsp;</div></div><div></div><img src ="http://www.cppblog.com/Onway/aggbug/154198.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Onway/" target="_blank">Onway</a> 2011-08-24 10:26 <a href="http://www.cppblog.com/Onway/articles/154198.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>安装GTK+(转)</title><link>http://www.cppblog.com/Onway/articles/154197.html</link><dc:creator>Onway</dc:creator><author>Onway</author><pubDate>Wed, 24 Aug 2011 02:24:00 GMT</pubDate><guid>http://www.cppblog.com/Onway/articles/154197.html</guid><wfw:comment>http://www.cppblog.com/Onway/comments/154197.html</wfw:comment><comments>http://www.cppblog.com/Onway/articles/154197.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Onway/comments/commentRss/154197.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Onway/services/trackbacks/154197.html</trackback:ping><description><![CDATA[<div><div>Ubuntu下GTK的安装</div><div>(转自http://www.linuxidc.com/Linux/2008-09/15955.htm)</div><div></div><div>apt-get install build-essential #这将安装gcc/g++/gdb/make 等基本编程工具</div><div></div><div>apt-get install gnome-core-devel #这将安装 libgtk2.0-dev libglib2.0-dev 等开发相关的库文件</div><div></div><div>apt-get install pkg-config #用于在编译GTK程序时自动找出头文件及库文件位置</div><div>apt-get install devhelp #这将安装 devhelp GTK文档查看程序</div><div></div><div>apt-get install libglib2.0-doc libgtk2.0-doc #这将安装 gtk/glib 的API参考手册及其它帮助文档</div><div></div><div>apt-get install glade libglade2-dev #这将安装基于GTK的界面GTK是开发Gnome窗口的c/c++语言图形库。</div><div></div><div>apt-get install libgtk2.0*, gtk+2.0所需的所有文件统通下载安装完毕。</div><div></div><div>应用程序编译命令：gcc test.c `pkg-config --cflags --libs gtk+-2.0`，编译通过，运行正常。</div><div></div><div>pkg-config是一个用来管理包的程序，在控制台输入 pkg-config --cflags --libs gtk+-2.0，可以发现输出的文本包括了gcc编译gtk+2.0所需要的所有选项（头文件目录和库文件）。</div><div></div><div>这里有一点需要注意， gcc test.c `pkg-config --cflags --libs gtk+-2.0`, pkg-config --cflags --libs gtk+-2.0两侧的引号并不是真正的引号，而是键盘数字件那一行，最左边的那个字符。如果错用了单引号，gcc无法使用 pkg-config --cflags --libs gtk+-2.0产生的文本作为编译选项。构造程序。<br /><br /><hr /><div><div>[Linux]安装GTK全攻略(自己走过的弯路不希望别人再走)</div><div>(转自http://blogger.org.cn/blog/more.asp?name=airclh&amp;id=27104)</div><div></div><div>一、 &nbsp; &nbsp; &nbsp; &nbsp;所需的源码包</div><div></div><div>1. GNU make 工具</div><div>2. GNU gettext 软件包（当系统上没有 gettext() 函数的时候需要）</div><div>3. GNU libiconv 库（当系统上没有 iconv() 函数的时候需要）</div><div>4. fontconfig库</div><div>fontconfig 是提供系统范围内字体设置，定制和允许应用程序访问的函数库。</div><div>5. FreeType库</div><div>GTK+(基于DirectFB)的字体绘制是通过pango+freetype+fontconfig三者协作来完成的，其中，fontconfig负责字体的管理和配置，freetype负责单个字符的绘制，pango则完成对文字的排版布局。Freetype是一个操作字体的函数库，它不但可以处理点阵字体，也可以处理多种矢量字体，包括truetype字体，为上层应用程序提供了一个统一的调用接口。</div><div>6. libpng库</div><div>libpng软件包包含 libpng 库，这些库被其他程序用于读写png文件。PNG 库是用来创立和操作PNG 格式的图形文件.PNG 格式是设计来替代GIF,它对于更小范围的TIFF(标记图象文件格式)来说, 有了很多的进步和拓展并且减少了关于专利权的麻烦.</div><div>7. jpegsrc库</div><div>能够使用JPEG算法压缩文件。</div><div>8. tiff库</div><div>tiff库被很多程序用于读写tiff文件。</div><div>9.pkg-config 工具</div><div>pkgconfig 包括 pkg-config 程序，用来在编译脚本中向编译器传递头文件包含路径或库文件路径。</div><div>对于支持 pkg-config 工具的 GTK+ 及其依赖库来说，库的头文件的搜索路径的设置变成了对 .pc 文件搜索路径的设置。.pc 文件的搜索路径是通过环境变量 PKG_CONFIG_PATH 来设置的，pkg-config 将按照设置路径的先后顺序进行搜索，直到找到指定的 .pc 文件为止。</div><div>10. GLib 库</div><div>GLib是GTK+和GNOME工程的基础底层核心程序库，创建 GDK 和 GTK 应用程序时该库可提供许多有用的定义和函数，是一个综合用途的实用的轻量级的C程序库，它提供C语言的常用的数据结构的定义、相关的处理函数，有趣而实用的宏，可移植的封装和一些运行时机能，如事件循环、线程、动态调用、对象系统等的API。</div><div>11. ATK 库</div><div>ATK 包包含了 ATK 库。ATK是可访问性工具箱（Accessibility Toolkit）的简称。ATK 为所有的GTK2程序提供了解决 Accessibility 需求的框架。</div><div>12. Cairo 库</div><div>Cairo，是一个跨平台的开放源代码的矢量图形函数库，可以提供高质量的显示和打印输出。Cairo提供一个稳定的用户层API，它可以提供现代化的图形处理管理能力，如绘制和填充，映射转换，合成（注意，是合成）与改变alpha半透明图像，高真文本显示等等。能够在不同的媒体上实现相同的输出。</div><div>13. Pango 库</div><div>Pango 库提供了底层的文本编排绘制生成函数, 一套生成整段文本布局的高层函数和帮助编辑多国文本的函数。</div><div>14. GTK+ 库</div><div>&nbsp;</div><div>&nbsp;</div><div>其中前五项一般比较新的Linux版本中，系统都会自带。需要注意的一个问题是如果GTK的安装路径为/opt/gtk时，在PKG_CONFIG_PATH中除了要添加/opt/gtk/lib/pkgconfig之外，还有加上/usr/lib/pkgconfig。因为安装在系统的库其.pc文件都在/usr/lib/pkgconfig中，想要在安装GTK时用到这些系统自带的库时，必须把路径设置清楚。</div><div>在收集安装GTK所需的源码包时最重要，也是最容易忽略的一个问题就是各个包之间版本的匹配问题。我在安装GTK就忽略了这个问题，结果走了很多弯路。解决这个问题最简单的办法就是登陆GTK+ 的网站":ftp://ftp.gtk.org/pub/gtk，在上面下载各种源码包。在这个站点上，每个GTK版本兼容的源码包都放在一个文件夹下。例如我选择安装GTK v2.6，只要在ftp://ftp.gtk.org/pub/gtk/v2.6中下载各个包即可。不过选择V2.6的朋友要严重注意一个问题，支持GTK V2.6的pango包有两个版本－1.8.0、1.8.1，1.8.0是一个失败的版本，如果选择它，在安装GTK时就会死活找不到pango库。我当时就是这个版本的受害者，花了很长时间也无法在安装GTK时连接pango库，后来在网上看到一个老外说这个版本有bug，只能使用1.8.1版本。妈的！这不坑人吗！</div><div>根据依赖关系的要求，库的安装要按照这样的先后顺序进行：GLib、Atk、Cairo、Pango、Gtk+。</div><div>二、 &nbsp; &nbsp; &nbsp; &nbsp;设置</div><div></div><div>主要包括对LD_LIBRARY_PATH和PKG_CONFIG_PATH的设置，具体如下：</div><div>&gt; export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH</div><div>&gt; export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig:$PKG_CONFIG_PATH</div><div>注意，如果想要使用系统中已有的fontconfig、FreeType等库，需要加上系统原有的库：</div><div>&gt; export LD_LIBRARY_PATH=/usr/lib</div><div>&gt; export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH</div><div>&gt; export PKG_CONFIG_PATH=/usr/lib/pkgconfig</div><div>&gt; export PKG_CONFIG_PATH=/usr/X11R6 /lib/pkgconfig:$PKG_CONFIG_PATH</div><div>&gt; export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig:$PKG_CONFIG_PATH</div><div>容易被人忽略的一点是LD_LIBRARY_PATH和PKG_CONFIG_PATH这两个环境变量只对当前的终端窗口有效。如果到了没有进行上述设置的终端窗口中，pkg-config 将找不到新安装库的.pc 文件、从而可能使后面进行的安装无法进行。(自己犯的一个简单却造成严重后果的错误，吐血提醒大家哦)</div><div>三、 &nbsp; &nbsp; &nbsp; &nbsp;源码包的安装</div><div></div><div>我安装的GTK版本为v2.6，用到的源码包包括：jpegsrc.v6b.tar.gz、libpng-1.2.8.tar.bz2、tiff-v3.6.1.tar.gz、pkgconfig-0.15.0.tar.gz、glib-2.6.6.tar.bz2、atk-1.9.0.tar.bz2、cairo-1.2.4.tar.gz、pango-1.8.1.tar.bz2、gtk+-2.6.9.tar.bz2。把它们都放在root的主目录下。</div><div>将 GTK+ 及其依赖库设置安装到同一个目录/opt/gtk下、而不是每一个库占用一个不同的目录，可以给以后的库的设置带来方便。而且，在将来不再需要这个版本的 GTK+ 及其依赖库的时候可以通过删除这个目录将它们简单地去除。</div><div>1． &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 安装pkgconfig</div><div></div><div>&gt; tar zxvf pkgconfig-0.15.0.tar.gz</div><div>&gt; cd /root/pkgconfig-0.15.0</div><div>&gt; ./configure</div><div>&gt; make</div><div>&gt; make install</div><div>&nbsp;</div><div>每个过程结束后，都可以用用 echo $? 检查是否执行安装成功。如果输出是 0，说明配置成功；0 之外的数字说明配置失败。在 Linux 系统上，可以用这个方法检查一个命令或程序在其结束后返回给系统的值是多少。一般 0 代表成功，非 0 表示程序异常退出。</div><div>2．安装glib</div><div></div><div>&gt; tar zjvf glib-2.6.6.tar.bz2</div><div>&gt; cd /root/ glib-2.6.6</div><div>&gt;./configure --prefix=/opt/gtk</div><div>&gt;make</div><div>&gt;make install</div><div>3．安装atk</div><div></div><div>&gt; tar zjvf atk-1.9.0.tar.bz2</div><div>&gt; cd /root/ atk-1.9.0</div><div>&gt;./configure --prefix=/opt/gtk</div><div>&gt;make</div><div>&gt;make install</div><div>4.安装cairo</div><div></div><div>&gt; tar zxvf cairo-1.2.4.tar.gz</div><div>&gt; cd /root/ cairo-1.2.4</div><div>&gt;./configure --prefix=/opt/gtk --with-x --enable-win32=no</div><div>&gt;make</div><div>&gt;make install</div><div>5.安装Pango</div><div></div><div>&gt; tar zxvf cairo-1.2.4.tar.gz</div><div>&gt; cd /root/ cairo-1.2.4</div><div>&gt;./configure --prefix=/opt/gtk --libdir=/opt/gtk/lib --with-x</div><div>&gt;make</div><div>&gt;make install</div><div>6．安装libpng</div><div></div><div>&gt; tar zjvf libpng-1.2.8.tar.bz2</div><div>&gt; cd /root/ libpng-1.2.8</div><div>&gt; make prefix=/opt/gtk \ZLIBINC=/opt/gtk/include ZLIBLIB=/opt/gtk/lib -f scripts/makefile.linux</div><div>&gt;make prefix=/opt/gtk install -f scripts/makefile.linux</div><div>7．安装libtiff(就是tiff)</div><div></div><div>&gt; tar zxvf tiff-v3.6.1.tar.gz</div><div>&gt; cd /root/ tiff-v3.6.1</div><div>&gt; ./configure --prefix=/opt/gtk --noninteractive \ --with-DIR_MAN=/opt/gtk/share/man</div><div>&gt; make</div><div>&gt; make install</div><div>8．安装libjpeg(就是jpegsrv)</div><div></div><div>&gt; tar zxvf jpegsrc.v6b.tar.gz</div><div>&gt; cd /root/jpeg-6b</div><div>&gt; ./configure --enable-static --enable-shared --prefix=/opt/gtk</div><div>&gt; make</div><div>&gt; make install</div><div>注：jpeg默认不share library，因此要手工指定--enable-shared，一般安装lib时这一点都是要注意的。</div><div>10．安装gtk</div><div></div><div>&gt; tar zjvf gtk+-2.6.9.tar.bz2</div><div>&gt; cd /root/ gtk+-2.6.9</div><div>&gt; ./configure --prefix=/opt/gtk --with-x --without-libjpeg</div><div>&gt; make</div><div>&gt; make install</div><div></div><div>四、 &nbsp; &nbsp; &nbsp; &nbsp;检验是否正确安装GTK</div><div></div><div>为了检验是否正确安装GTK，利用GTK编写一个简单的程序，这个程序创建 200x200 大小的窗口。源码如下：</div><div>#include &lt;gtk/gtk.h&gt;</div><div>int main( int argc,</div><div>char *argv[] )</div><div>{</div><div>GtkWidget *window;</div><div>gtk_init (&amp;argc, &amp;argv);</div><div>window = gtk_window_new (GTK_WINDOW_TOPLEVEL);</div><div>gtk_widget_show (window);</div><div>gtk_main ();</div><div>return 0;</div><div>}</div><div>用 gcc 编译上面的程序：</div><div>gcc base.c &#8211;o base `pkg-config &#8211;cflags &#8211;libs gtk+2.0`</div><div>成功编译后，使用命令./base运行该程序。</div><div>注意上面编译命令中使用的单引号类型是很重要的。(译者注：这里使用了&#8220;命令替换&#8221;。命令替换(command substitution)使得可以捕获一个命令的输出而在另一个命令中替换它。这个单引号不是回车键左边的那个，而是ESC键下面的那个。)&nbsp;</div></div></div></div><img src ="http://www.cppblog.com/Onway/aggbug/154197.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Onway/" target="_blank">Onway</a> 2011-08-24 10:24 <a href="http://www.cppblog.com/Onway/articles/154197.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DD牛的背包九讲</title><link>http://www.cppblog.com/Onway/articles/137617.html</link><dc:creator>Onway</dc:creator><author>Onway</author><pubDate>Tue, 28 Dec 2010 11:07:00 GMT</pubDate><guid>http://www.cppblog.com/Onway/articles/137617.html</guid><wfw:comment>http://www.cppblog.com/Onway/comments/137617.html</wfw:comment><comments>http://www.cppblog.com/Onway/articles/137617.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Onway/comments/commentRss/137617.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Onway/services/trackbacks/137617.html</trackback:ping><description><![CDATA[出处不详。<br><br>
<div class=postbody><font color=#000000 size=3 face=宋体>P01: 01背包问题 <br>题目 <br>有N件物品和一个容量为V的背包。第i件物品的费用是c[i]，价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量，且价值总和最大。 <br><br>基本思路 <br>这是最基础的背包问题，特点是：每种物品仅有一件，可以选择放或不放。 <br><br>用子问题定义状态：即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是：f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}。 <br><br>这个方程非常重要，基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下：&#8220;将前i件物品放入容量为v的背包中&#8221;这个子问题，若只考虑第i件物品的策略（放或不放），那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品，那么问题就转化为&#8220;前i-1件物品放入容量为v的背包中&#8221;；如果放第i件物品，那么问题就转化为&#8220;前i-1件物品放入剩下的容量为v-c[i]的背包中&#8221;，此时能获得的最大价值就是f [i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。 <br><br>注意f[i][v]有意义当且仅当存在一个前i件物品的子集，其费用总和为v。所以按照这个方程递推完毕后，最终的答案并不一定是f[N] [V]，而是f[N][0..V]的最大值。如果将状态的定义中的&#8220;恰&#8221;字去掉，在转移方程中就要再加入一项f[i][v-1]，这样就可以保证f[N] [V]就是最后的答案。至于为什么这样就可以，由你自己来体会了。 <br><br>优化空间复杂度 <br>以上方法的时间和空间复杂度均为O(N*V)，其中时间复杂度基本已经不能再优化了，但空间复杂度却可以优化到O(V)。 <br><br>先考虑上面讲的基本思路如何实现，肯定是有一个主循环i=1..N，每次算出来二维数组f[i][0..V]的所有值。那么，如果只用一个数组f [0..V]，能不能保证第i次循环结束后f[v]中表示的就是我们定义的状态f[i][v]呢？f[i][v]是由f[i-1][v]和f[i-1] [v-c[i]]两个子问题递推而来，能否保证在推f[i][v]时（也即在第i次主循环中推f[v]时）能够得到f[i-1][v]和f[i-1][v -c[i]]的值呢？事实上，这要求在每次主循环中我们以v=V..0的顺序推f[v]，这样才能保证推f[v]时f[v-c[i]]保存的是状态f[i -1][v-c[i]]的值。伪代码如下： <br><br>for i=1..N <br>for v=V..0 <br>f[v]=max{f[v],f[v-c[i]]+w[i]}; <br><br>其中的f[v]=max{f[v],f[v-c[i]]}一句恰就相当于我们的转移方程f[i][v]=max{f[i-1][v],f[i- 1][v-c[i]]}，因为现在的f[v-c[i]]就相当于原来的f[i-1][v-c[i]]。如果将v的循环顺序从上面的逆序改成顺序的话，那么则成了f[i][v]由f[i][v-c[i]]推知，与本题意不符，但它却是另一个重要的背包问题P02最简捷的解决方案，故学习只用一维数组解01背包问题是十分必要的。 <br><br>总结 <br>01背包问题是最基本的背包问题，它包含了背包问题中设计状态、方程的最基本思想，另外，别的类型的背包问题往往也可以转换成01背包问题求解。故一定要仔细体会上面基本思路的得出方法，状态转移方程的意义，以及最后怎样优化的空间复杂度。 <br><br>P02: 完全背包问题 <br>题目 <br>有N种物品和一个容量为V的背包，每种物品都有无限件可用。第i种物品的费用是c[i]，价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量，且价值总和最大。 <br><br>基本思路 <br>这个问题非常类似于01背包问题，所不同的是每种物品有无限件。也就是从每种物品的角度考虑，与它相关的策略已并非取或不取两种，而是有取0件、取1件、取2件&#8230;&#8230;等很多种。如果仍然按照解01背包时的思路，令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值。仍然可以按照每种物品不同的策略写出状态转移方程，像这样：f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0&lt;=k*c[i]&lt;= v}。这跟01背包问题一样有O(N*V)个状态需要求解，但求解每个状态的时间则不是常数了，求解状态f[i][v]的时间是O(v/c[i])，总的复杂度是超过O(VN)的。 <br><br>将01背包问题的基本思路加以改进，得到了这样一个清晰的方法。这说明01背包问题的方程的确是很重要，可以推及其它类型的背包问题。但我们还是试图改进这个复杂度。 <br><br>一个简单有效的优化 <br>完全背包问题有一个很简单有效的优化，是这样的：若两件物品i、j满足c[i]&lt;=c[j]且w[i]&gt;=w[j]，则将物品j去掉，不用考虑。这个优化的正确性显然：任何情况下都可将价值小费用高得j换成物美价廉的i，得到至少不会更差的方案。对于随机生成的数据，这个方法往往会大大减少物品的件数，从而加快速度。然而这个并不能改善最坏情况的复杂度，因为有可能特别设计的数据可以一件物品也去不掉。 <br><br>转化为01背包问题求解 <br>既然01背包问题是最基本的背包问题，那么我们可以考虑把完全背包问题转化为01背包问题来解。最简单的想法是，考虑到第i种物品最多选V/c [i]件，于是可以把第i种物品转化为V/c[i]件费用及价值均不变的物品，然后求解这个01背包问题。这样完全没有改进基本思路的时间复杂度，但这毕竟给了我们将完全背包问题转化为01背包问题的思路：将一种物品拆成多件物品。 <br><br>更高效的转化方法是：把第i种物品拆成费用为c[i]*2^k、价值为w[i]*2^k的若干件物品，其中k满足c[i]*2^k&lt;V。这是二进制的思想，因为不管最优策略选几件第i种物品，总可以表示成若干个2^k件物品的和。这样把每种物品拆成O(log(V/c[i]))件物品，是一个很大的改进。 但我们有更优的O(VN)的算法。 * O(VN)的算法 这个算法使用一维数组，先看伪代码： &lt;pre class"example"&gt; for i=1..N for v=0..V f[v]=max{f[v],f[v-c[i]]+w[i]}; <br><br><br><br>你会发现，这个伪代码与P01的伪代码只有v的循环次序不同而已。为什么这样一改就可行呢？首先想想为什么P01中要按照v=V..0的逆序来循环。这是因为要保证第i次循环中的状态f[i][v]是由状态f[i-1][v-c[i]]递推而来。换句话说，这正是为了保证每件物品只选一次，保证在考虑&#8220;选入第i件物品&#8221;这件策略时，依据的是一个绝无已经选入第i件物品的子结果f[i-1][v-c[i]]。而现在完全背包的特点恰是每种物品可选无限件，所以在考虑&#8220;加选一件第i种物品&#8221;这种策略时，却正需要一个可能已选入第i种物品的子结果f[i][v-c[i]]，所以就可以并且必须采用v= 0..V的顺序循环。这就是这个简单的程序为何成立的道理。 <br><br>这个算法也可以以另外的思路得出。例如，基本思路中的状态转移方程可以等价地变形成这种形式：f[i][v]=max{f[i-1][v],f[i][v-c[i]]+w[i]}，将这个方程用一维数组实现，便得到了上面的伪代码。 <br><br>总结 <br>完全背包问题也是一个相当基础的背包问题，它有两个状态转移方程，分别在&#8220;基本思路&#8221;以及&#8220;O(VN)的算法&#8220;的小节中给出。希望你能够对这两个状态转移方程都仔细地体会，不仅记住，也要弄明白它们是怎么得出来的，最好能够自己想一种得到这些方程的方法。事实上，对每一道动态规划题目都思考其方程的意义以及如何得来，是加深对动态规划的理解、提高动态规划功力的好方法。 <br><br>P03: 多重背包问题 <br>题目 <br>有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用，每件费用是c[i]，价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量，且价值总和最大。 <br><br>基本算法 <br>这题目和完全背包问题很类似。基本的方程只需将完全背包问题的方程略微一改即可，因为对于第i种物品有n[i]+1种策略：取0件，取1件&#8230;&#8230;取 n[i]件。令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值，则：f[i][v]=max{f[i-1][v-k*c[i]]+ k*w[i]|0&lt;=k&lt;=n[i]}。复杂度是O(V*∑n[i])。 <br><br>转化为01背包问题 <br>另一种好想好写的基本方法是转化为01背包求解：把第i种物品换成n[i]件01背包中的物品，则得到了物品数为∑n[i]的01背包问题，直接求解，复杂度仍然是O(V*∑n[i])。 <br><br>但是我们期望将它转化为01背包问题之后能够像完全背包一样降低复杂度。仍然考虑二进制的思想，我们考虑把第i种物品换成若干件物品，使得原问题中第i种物品可取的每种策略——取0..n[i]件——均能等价于取若干件代换以后的物品。另外，取超过n[i]件的策略必不能出现。 <br><br>方法是：将第i种物品分成若干件物品，其中每件物品有一个系数，这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为 1,2,4,...,2^(k-1),n[i]-2^k+1，且k是满足n[i]-2^k+1&gt;0的最大整数。例如，如果n[i]为13，就将这种物品分成系数分别为1,2,4,6的四件物品。 <br><br>分成的这几件物品的系数和为n[i]，表明不可能取多于n[i]件的第i种物品。另外这种方法也能保证对于0..n[i]间的每一个整数，均可以用若干个系数的和表示，这个证明可以分0..2^k-1和2^k..n[i]两段来分别讨论得出，并不难，希望你自己思考尝试一下。 <br><br>这样就将第i种物品分成了O(log n[i])种物品，将原问题转化为了复杂度为O(V*∑log n[i])的01背包问题，是很大的改进。 <br><br>O(VN)的算法 <br>多重背包问题同样有O(VN)的算法。这个算法基于基本算法的状态转移方程，但应用单调队列的方法使每个状态的值可以以均摊O(1)的时间求解。由于用单调队列优化的DP已超出了NOIP的范围，故本文不再展开讲解。我最初了解到这个方法是在楼天成的&#8220;男人八题&#8221;幻灯片上。 <br><br>小结 <br>这里我们看到了将一个算法的复杂度由O(V*∑n[i])改进到O(V*∑log n[i])的过程，还知道了存在应用超出NOIP范围的知识的O(VN)算法。希望你特别注意&#8220;拆分物品&#8221;的思想和方法，自己证明一下它的正确性，并用尽量简洁的程序来实现。 <br><br><br><br>P04: 混合三种背包问题 <br>问题 <br>如果将P01、P02、P03混合起来。也就是说，有的物品只可以取一次（01背包），有的物品可以取无限次（完全背包），有的物品可以取的次数有一个上限（多重背包）。应该怎么求解呢？ <br><br>01背包与完全背包的混合 <br>考虑到在P01和P02中最后给出的伪代码只有一处不同，故如果只有两类物品：一类物品只能取一次，另一类物品可以取无限次，那么只需在对每个物品应用转移方程时，根据物品的类别选用顺序或逆序的循环即可，复杂度是O(VN)。伪代码如下： <br><br>for i=1..N <br>if 第i件物品是01背包 <br>for v=V..0 <br>f[v]=max{f[v],f[v-c[i]]+w[i]}; <br>else if 第i件物品是完全背包 <br>for v=0..V <br>f[v]=max{f[v],f[v-c[i]]+w[i]}; <br><br>再加上多重背包 <br>如果再加上有的物品最多可以取有限次，那么原则上也可以给出O(VN)的解法：遇到多重背包类型的物品用单调队列解即可。但如果不考虑超过NOIP范围的算法的话，用P03中将每个这类物品分成O(log n[i])个01背包的物品的方法也已经很优了。 <br><br>小结 <br>有人说，困难的题目都是由简单的题目叠加而来的。这句话是否公理暂且存之不论，但它在本讲中已经得到了充分的体现。本来01背包、完全背包、多重背包都不是什么难题，但将它们简单地组合起来以后就得到了这样一道一定能吓倒不少人的题目。但只要基础扎实，领会三种基本背包问题的思想，就可以做到把困难的题目拆分成简单的题目来解决。 <br>P05: 二维费用的背包问题 <br>问题 <br>二维费用的背包问题是指：对于每件物品，具有两种不同的费用；选择这件物品必须同时付出这两种代价；对于每种代价都有一个可付出的最大值（背包容量）。问怎样选择物品可以得到最大的价值。设这两种代价分别为代价1和代价2，第i件物品所需的两种代价分别为a[i]和b[i]。两种代价可付出的最大值（两种背包容量）分别为V和U。物品的价值为w[i]。 <br><br>算法 <br>费用加了一维，只需状态也加一维即可。设f[i][v][u]表示前i件物品付出两种代价分别为v和u时可获得的最大价值。状态转移方程就是：f [i][v][u]=max{f[i-1][v][u],f[i-1][v-a[i]][u-b[i]]+w[i]}。如前述方法，可以只使用二维的数组：当每件物品只可以取一次时变量v和u采用顺序的循环，当物品有如完全背包问题时采用逆序的循环。当物品有如多重背包问题时拆分物品。 <br><br>物品总个数的限制 <br>有时，&#8220;二维费用&#8221;的条件是以这样一种隐含的方式给出的：最多只能取M件物品。这事实上相当于每件物品多了一种&#8220;件数&#8221;的费用，每个物品的件数费用均为1，可以付出的最大件数费用为M。换句话说，设f[v][m]表示付出费用v、最多选m件时可得到的最大价值，则根据物品的类型（01、完全、多重）用不同的方法循环更新，最后在f[0..V][0..M]范围内寻找答案。 <br><br>另外，如果要求&#8220;恰取M件物品&#8221;，则在f[0..V][M]范围内寻找答案。 <br><br>小结 <br>事实上，当发现由熟悉的动态规划题目变形得来的题目时，在原来的状态中加一纬以满足新的限制是一种比较通用的方法。希望你能从本讲中初步体会到这种方法。 <br><br>P06: 分组的背包问题 <br>问题 <br>有N件物品和一个容量为V的背包。第i件物品的费用是c[i]，价值是w[i]。这些物品被划分为若干组，每组中的物品互相冲突，最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量，且价值总和最大。 <br><br>算法 <br>这个问题变成了每组物品有若干种策略：是选择本组的某一件，还是一件都不选。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值，则有f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]|物品i属于第k组}。 <br><br>使用一维数组的伪代码如下： <br><br>for 所有的组k <br>for 所有的i属于组k <br>for v=V..0 <br>f[v]=max{f[v],f[v-c[i]]+w[i]} <br><br>另外，显然可以对每组中的物品应用P02中&#8220;一个简单有效的优化&#8221;。 <br><br>小结 <br>分组的背包问题将彼此互斥的若干物品称为一个组，这建立了一个很好的模型。不少背包问题的变形都可以转化为分组的背包问题（例如P07），由分组的背包问题进一步可定义&#8220;泛化物品&#8221;的概念，十分有利于解题。 <br><br>P07: 有依赖的背包问题 <br>简化的问题 <br>这种背包问题的物品间存在某种&#8220;依赖&#8221;的关系。也就是说，i依赖于j，表示若选物品i，则必须选物品j。为了简化起见，我们先设没有某个物品既依赖于别的物品，又被别的物品所依赖；另外，没有某件物品同时依赖多件物品。 <br><br>算法 <br>这个问题由NOIP2006金明的预算方案一题扩展而来。遵从该题的提法，将不依赖于别的物品的物品称为&#8220;主件&#8221;，依赖于某主件的物品称为&#8220;附件&#8221;。由这个问题的简化条件可知所有的物品由若干主件和依赖于每个主件的一个附件集合组成。 <br><br>按照背包问题的一般思路，仅考虑一个主件和它的附件集合。可是，可用的策略非常多，包括：一个也不选，仅选择主件，选择主件后再选择一个附件，选择主件后再选择两个附件&#8230;&#8230;无法用状态转移方程来表示如此多的策略。（事实上，设有n个附件，则策略有2^n+1个，为指数级。） <br><br>考虑到所有这些策略都是互斥的（也就是说，你只能选择一种策略），所以一个主件和它的附件集合实际上对应于P06中的一个物品组，每个选择了主件又选择了若干个附件的策略对应于这个物品组中的一个物品，其费用和价值都是这个策略中的物品的值的和。但仅仅是这一步转化并不能给出一个好的算法，因为物品组中的物品还是像原问题的策略一样多。 <br><br>再考虑P06中的一句话： 可以对每组中的物品应用P02中&#8220;一个简单有效的优化&#8221;。这提示我们，对于一个物品组中的物品，所有费用相同的物品只留一个价值最大的，不影响结果。所以，我们可以对主件i的&#8220;附件集合&#8221;先进行一次01背包，得到费用依次为0..V-c[i]所有这些值时相应的最大价值f'[0..V-c[i]]。那么这个主件及它的附件集合相当于V-c[i]+1个物品的物品组，其中费用为c[i]+k的物品的价值为f'[k]+w[i]。也就是说原来指数级的策略中有很多策略都是冗余的，通过一次01背包后，将主件i转化为 V-c[i]+1个物品的物品组，就可以直接应用P06的算法解决问题了。 <br><br>更一般的问题 <br>更一般的问题是：依赖关系以图论中&#8220;森林&#8221;的形式给出（森林即多叉树的集合），也就是说，主件的附件仍然可以具有自己的附件集合，限制只是每个物品最多只依赖于一个物品（只有一个主件）且不出现循环依赖。 <br><br>解决这个问题仍然可以用将每个主件及其附件集合转化为物品组的方式。唯一不同的是，由于附件可能还有附件，就不能将每个附件都看作一个一般的01 背包中的物品了。若这个附件也有附件集合，则它必定要被先转化为物品组，然后用分组的背包问题解出主件及其附件集合所对应的附件组中各个费用的附件所对应的价值。 <br><br>事实上，这是一种树形DP，其特点是每个父节点都需要对它的各个儿子的属性进行一次DP以求得自己的相关属性。这已经触及到了&#8220;泛化物品&#8221;的思想。看完P08后，你会发现这个&#8220;依赖关系树&#8221;每一个子树都等价于一件泛化物品，求某节点为根的子树对应的泛化物品相当于求其所有儿子的对应的泛化物品之和。 <br><br>小结 <br>NOIP2006的那道背包问题我做得很失败，写了上百行的代码，却一分未得。后来我通过思考发现通过引入&#8220;物品组&#8221;和&#8220;依赖&#8221;的概念可以加深对这题的理解，还可以解决它的推广问题。用物品组的思想考虑那题中极其特殊的依赖关系：物品不能既作主件又作附件，每个主件最多有两个附件，可以发现一个主件和它的两个附件等价于一个由四个物品组成的物品组，这便揭示了问题的某种本质。 <br><br>我想说：失败不是什么丢人的事情，从失败中全无收获才是。 <br><br>P08: 泛化物品 <br>定义 <br>考虑这样一种物品，它并没有固定的费用和价值，而是它的价值随着你分配给它的费用而变化。这就是泛化物品的概念。 <br><br>更严格的定义之。在背包容量为V的背包问题中，泛化物品是一个定义域为0..V中的整数的函数h，当分配给它的费用为v时，能得到的价值就是h(v)。 <br><br>这个定义有一点点抽象，另一种理解是一个泛化物品就是一个数组h[0..V]，给它费用v，可得到价值h[V]。 <br><br>一个费用为c价值为w的物品，如果它是01背包中的物品，那么把它看成泛化物品，它就是除了h(c)=w其它函数值都为0的一个函数。如果它是完全背包中的物品，那么它可以看成这样一个函数，仅当v被c整除时有h(v)=v/c*w，其它函数值均为0。如果它是多重背包中重复次数最多为n的物品，那么它对应的泛化物品的函数有h(v)=v/c*w仅当v被c整除且v/c&lt;=n，其它情况函数值均为0。 <br><br>一个物品组可以看作一个泛化物品h。对于一个0..V中的v，若物品组中不存在费用为v的的物品，则h(v)=0，否则h(v)为所有费用为v的物品的最大价值。P07中每个主件及其附件集合等价于一个物品组，自然也可看作一个泛化物品。 <br><br>泛化物品的和 <br>如果面对两个泛化物品h和l，要用给定的费用从这两个泛化物品中得到最大的价值，怎么求呢？事实上，对于一个给定的费用v，只需枚举将这个费用如何分配给两个泛化物品就可以了。同样的，对于0..V的每一个整数v，可以求得费用v分配到h和l中的最大价值f(v)。也即f(v)=max{h(k) +l(v-k)|0&lt;=k&lt;=v}。可以看到，f也是一个由泛化物品h和l决定的定义域为0..V的函数，也就是说，f是一个由泛化物品h和 l决定的泛化物品。 <br><br>由此可以定义泛化物品的和：h、l都是泛化物品，若泛化物品f满足f(v)=max{h(k)+l(v-k)|0&lt;=k&lt;=v}，则称f是h与l的和，即f=h+l。这个运算的时间复杂度是O(V^2)。 <br><br>泛化物品的定义表明：在一个背包问题中，若将两个泛化物品代以它们的和，不影响问题的答案。事实上，对于其中的物品都是泛化物品的背包问题，求它的答案的过程也就是求所有这些泛化物品之和的过程。设此和为s，则答案就是s[0..V]中的最大值。 <br><br>背包问题的泛化物品 <br>一个背包问题中，可能会给出很多条件，包括每种物品的费用、价值等属性，物品之间的分组、依赖等关系等。但肯定能将问题对应于某个泛化物品。也就是说，给定了所有条件以后，就可以对每个非负整数v求得：若背包容量为v，将物品装入背包可得到的最大价值是多少，这可以认为是定义在非负整数集上的一件泛化物品。这个泛化物品——或者说问题所对应的一个定义域为非负整数的函数——包含了关于问题本身的高度浓缩的信息。一般而言，求得这个泛化物品的一个子域（例如0..V）的值之后，就可以根据这个函数的取值得到背包问题的最终答案。 <br><br>综上所述，一般而言，求解背包问题，即求解这个问题所对应的一个函数，即该问题的泛化物品。而求解某个泛化物品的一种方法就是将它表示为若干泛化物品的和然后求之。 <br><br>小结 <br>本讲可以说都是我自己的原创思想。具体来说，是我在学习函数式编程的 Scheme 语言时，用函数编程的眼光审视各类背包问题得出的理论。这一讲真的很抽象，也许在&#8220;模型的抽象程度&#8221;这一方面已经超出了NOIP的要求，所以暂且看不懂也没关系。相信随着你的OI之路逐渐延伸，有一天你会理解的。 <br><br>我想说：&#8220;思考&#8221;是一个OIer最重要的品质。简单的问题，深入思考以后，也能发现更多。 <br><br>P09: 背包问题问法的变化 <br>以上涉及的各种背包问题都是要求在背包容量（费用）的限制下求可以取到的最大价值，但背包问题还有很多种灵活的问法，在这里值得提一下。但是我认为，只要深入理解了求背包问题最大价值的方法，即使问法变化了，也是不难想出算法的。 <br><br>例如，求解最多可以放多少件物品或者最多可以装满多少背包的空间。这都可以根据具体问题利用前面的方程求出所有状态的值（f数组）之后得到。 <br><br>还有，如果要求的是&#8220;总价值最小&#8221;&#8220;总件数最小&#8221;，只需简单的将上面的状态转移方程中的max改成min即可。 <br><br>下面说一些变化更大的问法。 <br><br>输出方案 <br>一般而言，背包问题是要求一个最优值，如果要求输出这个最优值的方案，可以参照一般动态规划问题输出方案的方法：记录下每个状态的最优值是由状态转移方程的哪一项推出来的，换句话说，记录下它是由哪一个策略推出来的。便可根据这条策略找到上一个状态，从上一个状态接着向前推即可。 <br><br>还是以01背包为例，方程为f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}。再用一个数组g[i] [v]，设g[i][v]=0表示推出f[i][v]的值时是采用了方程的前一项（也即f[i][v]=f[i-1][v]），g[i][v]表示采用了方程的后一项。注意这两项分别表示了两种策略：未选第i个物品及选了第i个物品。那么输出方案的伪代码可以这样写（设最终状态为f[N][V]）： <br><br>i=N <br>v=V <br>while(i&gt;0) <br>if(g[i][v]==0) <br>print "未选第i项物品" <br>else if(g[i][v]==1) <br>print "选了第i项物品" <br>v=v-c[i] <br><br>另外，采用方程的前一项或后一项也可以在输出方案的过程中根据f[i][v]的值实时地求出来，也即不须纪录g数组，将上述代码中的g[i] [v]==0改成f[i][v]==f[i-1][v]，g[i][v]==1改成f[i][v]==f[i-1][v-c[i]]+w[i]也可。 <br><br>输出字典序最小的最优方案 <br>这里&#8220;字典序最小&#8221;的意思是1..N号物品的选择方案排列出来以后字典序最小。以输出01背包最小字典序的方案为例。 <br><br>一般而言，求一个字典序最小的最优方案，只需要在转移时注意策略。首先，子问题的定义要略改一些。我们注意到，如果存在一个选了物品1的最优方案，那么答案一定包含物品1，原问题转化为一个背包容量为v-c[1]，物品为2..N的子问题。反之，如果答案不包含物品1，则转化成背包容量仍为V，物品为2..N的子问题。不管答案怎样，子问题的物品都是以i..N而非前所述的1..i的形式来定义的，所以状态的定义和转移方程都需要改一下。但也许更简易的方法是先把物品逆序排列一下，以下按物品已被逆序排列来叙述。 <br><br>在这种情况下，可以按照前面经典的状态转移方程来求值，只是输出方案的时候要注意：从N到1输入时，如果f[i][v]==f[i-v]及f[i][v]==f[i-1][f-c[i]]+w[i]同时成立，应该按照后者（即选择了物品i）来输出方案。 <br><br>求方案总数 <br>对于一个给定了背包容量、物品费用、物品间相互关系（分组、依赖等）的背包问题，除了再给定每个物品的价值后求可得到的最大价值外，还可以得到装满背包或将背包装至某一指定容量的方案总数。 <br><br>对于这类改变问法的问题，一般只需将状态转移方程中的max改成sum即可。例如若每件物品均是01背包中的物品，转移方程即为f[i][v]=sum{f[i-1][v],f[i-1][v-c[i]]+w[i]}，初始条件f[0][0]=1。 <br><br>事实上，这样做可行的原因在于状态转移方程已经考察了所有可能的背包组成方案。 <br><br>最优方案的总数 <br>这里的最优方案是指物品总价值最大的方案。还是以01背包为例。 <br><br>结合求最大总价值和方案总数两个问题的思路，最优方案的总数可以这样求：f[i][v]意义同前述，g[i][v]表示这个子问题的最优方案的总数，则在求f[i][v]的同时求g[i][v]的伪代码如下： <br><br>for i=1..N <br>for v=0..V <br>f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]} <br>g[i][v]=0 <br>if(f[i][v]==f[i-1][v]) <br>inc(g[i][v],g[i-1][v] <br>if(f[i][v]==f[i-1][v-c[i]]+w[i]) <br>inc(g[i][v],g[i-1][v-c[i]]) <br><br>如果你是第一次看到这样的问题，请仔细体会上面的伪代码。 <br><br>小结 <br>显然，这里不可能穷尽背包类动态规划问题所有的问法。甚至还存在一类将背包类动态规划问题与其它领域（例如数论、图论）结合起来的问题，在这篇论背包问题的专文中也不会论及。但只要深刻领会前述所有类别的背包问题的思路和状态转移方程，遇到其它的变形问法，只要题目难度还属于NOIP，应该也不难想出算法。 <br><br>触类旁通、举一反三，应该也是一个OIer应有的品质吧。</font></div>
<img src ="http://www.cppblog.com/Onway/aggbug/137617.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Onway/" target="_blank">Onway</a> 2010-12-28 19:07 <a href="http://www.cppblog.com/Onway/articles/137617.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++格式控制 (经典！)</title><link>http://www.cppblog.com/Onway/articles/136530.html</link><dc:creator>Onway</dc:creator><author>Onway</author><pubDate>Wed, 15 Dec 2010 14:06:00 GMT</pubDate><guid>http://www.cppblog.com/Onway/articles/136530.html</guid><wfw:comment>http://www.cppblog.com/Onway/comments/136530.html</wfw:comment><comments>http://www.cppblog.com/Onway/articles/136530.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Onway/comments/commentRss/136530.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Onway/services/trackbacks/136530.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转自：http://blog.pfan.cn/aurora/18800.html格式控制&nbsp;&nbsp;&nbsp;&nbsp;当输入／输出的数据没有指定格式，它们都按缺省的格式输入／输出。然而，有时需要对数据格式进行控制。这时需利用ios类中定义的格式控制成员函数，通过调用它们来完成格式的设置。ios类的格式控制函数如下所示：                     ...&nbsp;&nbsp;<a href='http://www.cppblog.com/Onway/articles/136530.html'>阅读全文</a><img src ="http://www.cppblog.com/Onway/aggbug/136530.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Onway/" target="_blank">Onway</a> 2010-12-15 22:06 <a href="http://www.cppblog.com/Onway/articles/136530.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《路在何方》-转自博客园-marvinyane</title><link>http://www.cppblog.com/Onway/articles/132260.html</link><dc:creator>Onway</dc:creator><author>Onway</author><pubDate>Wed, 03 Nov 2010 01:23:00 GMT</pubDate><guid>http://www.cppblog.com/Onway/articles/132260.html</guid><wfw:comment>http://www.cppblog.com/Onway/comments/132260.html</wfw:comment><comments>http://www.cppblog.com/Onway/articles/132260.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Onway/comments/commentRss/132260.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Onway/services/trackbacks/132260.html</trackback:ping><description><![CDATA[<font size=5>转眼间就大四了，只能感慨下时间过的真快啊。刚上大学的时候整天想着离开校园到社会上展示自己，现在真的要走了，想问下自己准备好了吗？<br></font><font style="FONT-SIZE: 14pt">&nbsp; &nbsp; 计算机科学与技术，当初毫无概念的报上这个专业，具体怎么来到这个学校这个专业的我也不清楚了，不过幸运的是我们专业90%以上的人也不知道他们怎么来的，至少有点归属感了呵呵。随遇而安</font><font style="FONT-SIZE: 14pt">来到学校</font><font style="FONT-SIZE: 14pt">就开始了自己的计算机生涯，说实话我还是很喜欢这个专业，至少让我感觉到自己的人生价值，毕竟我们都是理科生都对自己的逻辑思维能力很自信嘛，所以哥们从此展开了我的计算机生涯。</font><br><font style="FONT-SIZE: 14pt">&nbsp; &nbsp; 我想对于一个初学者来说没有什么比他的入门导师更重要了，那时候我对于计算机的世界来说就是一张白纸，没想到被人泼墨了呵呵，我们大学第一学期学的编程语言是Java，简简单单的一学期就是在学习什么是面向对象了，可悲的是我还不知道什么是面向过程，再说难道编程语言就只有这样简简单单的两种分类吗？伴随着出入大学的新鲜感就这样度过了自己的大学一年级，那时候傻乎乎的以为我只要学好了Java就是高手了，呵呵，好清纯的感觉啊。</font><br><font style="FONT-SIZE: 14pt">&nbsp; &nbsp; 大学二年级，年轻嘛，就知道追女孩秀甜蜜了，把计算机基础的学习从体系结构、汇编、数据结构、离散数学等等都给落下了，一是因为自己整天想着和美女约会了没时间学习反正考试几个很简单（确切的说是80分很简单）二是自己根本不知道什么才是计算机的基础，那时候我还以为自己很牛B呢，整天在那学习web开发了，毕竟是学了java基础的，学习起J2EE来也很简单了，就开始学习SSH框架，JavaEE开发平台下的所有乱七八糟的东西几乎全部接触过了，偶尔还能用这点东西拿个奖什么的，自以为我大二的时候J2EE都这么牛B了我就是传说中的高手了，哈哈，那时候自己的感觉就是大丰收啊，老婆有了、荣誉有了（那个奖可是我们学校计算机的最高荣誉了呵呵），事业也有眉目了（自己在外面的小公司找个兼职做个网站什么的），唉，感觉生活一片美好的景象啊。</font><br><font style="FONT-SIZE: 14pt">&nbsp; &nbsp; 大学三年级上学期仍旧停留在那个阶段什么都不懂，还整天的J2EE、整天的约会，计算机网络、操作系统这些基础课程自己根本就看不上眼啊，当时就想哥都搞web开发了这些东西学起来有什么用啊，呵呵，那时候还有个感觉就是目空一切啊（充分理解了井底之蛙是什么意思），我们学校的老师也拿我当个宝贝，说我的水平现在放眼整个同龄界都应该算是可以的了，想想看自己算个pi啊？除了能做个网站还能干什么呢？</font><br><font style="FONT-SIZE: 14pt">&nbsp; &nbsp; 好吧，一切的转折点就在2010年1月1号了，我和她分手了，那个让我痴迷了一年半让我心碎了八个月的女孩分手了，具体的原因应该就是吵着吵着就放狠话就完了，呵呵，想想那时候真的很年轻啊，这样都能分手（我一直相信我们的感情很好，就是太傻了呵呵）。一个月后我知道我真得失去他了，痛苦的男人总是最可怕的嘛，我寒假没有回家自己一个人躲在一个出租房里思考自己的人生呵呵（现在想想挺好玩的）同时度过了自己二十岁的生日，想想自己一个奔三的人了，我有什么资本能够在这个社会上立足？记得当时啃着肉夹馍在漆黑的角落里抽泣的时候，那个忍不住给家里打电话哭了半个多小时的男孩真的彻底想明白了（真的不知道怎么想明白了CS专业不是学习web开发的，我想是自己以前应该有些概念了但是不想去面对吧，现在自己有了勇气了，或者说真的想给自己即一个挑战啊），我彻底抛弃了那个曾经引以为豪的web开发。</font><br><font style="FONT-SIZE: 14pt">&nbsp; &nbsp; 从3月到现在转眼5个月就过去了，自己仍旧走在当初经过三秒钟思考定下的路上，我想我就是这样不管对与错只要自己的选择我就没有放弃的（除了她），从图书馆借来了很多很多关于计算机科学知识的书籍，从网上查找着资料，到底想想我应该怎么走，我应该干什么？整天躲在平台上面做开发对于起我们这个名号啊，哥们可是搞CS的，科学啊呵呵，一不小心成个家了那就是科学家啊，虽然社会比较浮躁但是我们应该坚持自己的方向不要迷失在这个五光十色的计算机的世界里，否则我们怎么才能追赶上摩尔的速度呢？好吧，我决定做底层开发了，做一些和操作系统同一个层次上的东西，具体什么还没有想到，既然不知道具体做什么就从基础开始吧，哥连个C语言都没有学过啊，那就从C语言开始学起吧，抱着基本C语言的书就开始看呗，反正也有点编程语言的功底学习点基础的东西还应该没有多大的问题，虽然C语言博大到让我感慨无以复加的地步，我就想怎么这么多东西需要注意呢，怪不得人家都说JAVA好学呢，学习完C语言就是数据结构和算法分析了，我就纳闷了我们堂堂CS专业的人怎么对于这个还这么陌生呢？几乎就是从头开始学习了呵呵，从DP到搜索，从链表到图，乱七八糟的慢慢来呗，下面就是操作系统了，不知不觉彻底爱上了UNIX，我就想了像WIN这么垃圾的东西怎么会这么流行呢（没别的意思哈），每天都在迫不及待的学习着新知识，从基础操作到系统编程（好吧我知道下面的我还没有学习，至少憧憬下应该还可以吧）从网络编程到内核分析，从驱动开发到嵌入式哇哈哈这么多优秀的东西真有种久在樊笼里，复得返自然的感觉啊哇哈哈。</font><br><font style="FONT-SIZE: 14pt">&nbsp; &nbsp; 好吧我知道就我现在的水平来说我还是很菜很菜的，现在只是站在海边听见海啸还没看见大海长什么样呢，呵呵，不过哥们就有这么个品质什么也不怕，慢慢来呗，我感觉就按照我现在自己定制的学习计划来说给我三年我也是大牛！</font><br><font style="FONT-SIZE: 14pt">&nbsp; &nbsp; 其实我们有时候缺乏的就是亡羊补牢的勇气，失败了还可以从头再来，错误了改正就好。</font><br><font style="FONT-SIZE: 14pt">&nbsp; &nbsp; 其实我们一直在路上，敢问路在何方，路在脚下！</font><br><font style="FONT-SIZE: 14pt">&nbsp; &nbsp; 谨以此文祭奠大学逝去的光阴，逝去的爱情。</font>
<img src ="http://www.cppblog.com/Onway/aggbug/132260.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Onway/" target="_blank">Onway</a> 2010-11-03 09:23 <a href="http://www.cppblog.com/Onway/articles/132260.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《原创 计算机系学生大学四年应该这样过》-转自博客园-帅子</title><link>http://www.cppblog.com/Onway/articles/132259.html</link><dc:creator>Onway</dc:creator><author>Onway</author><pubDate>Wed, 03 Nov 2010 01:22:00 GMT</pubDate><guid>http://www.cppblog.com/Onway/articles/132259.html</guid><wfw:comment>http://www.cppblog.com/Onway/comments/132259.html</wfw:comment><comments>http://www.cppblog.com/Onway/articles/132259.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Onway/comments/commentRss/132259.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Onway/services/trackbacks/132259.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 18pt"><strong><font style="FONT-SIZE: 9pt">1.<br></font></strong><strong><font face="宋体 "><font style="FONT-SIZE: 9pt">极端的社会舆论</font></font></strong></p>
<p style="FONT-SIZE: 18pt"><font face="宋体 "><font style="FONT-SIZE: 9pt">每每看到大学生就业报告里提到计算机系学生失业人数最多时，我就想</font></font><font style="FONT-SIZE: 9pt">mn</font><font face="宋体 "><font style="FONT-SIZE: 9pt">，什么原因导致了这种现象的发生，在中国软件还处于比较初级的阶段时，市场对软件人才的需求应该每年在大幅的递增，可是大学里培养出来的计算机科班人才质量却每况愈下，甚至还不如一个软件培训机构两三个月训练出来的人好用，为什么</font></font><font style="FONT-SIZE: 9pt">?</font><font face="宋体 "><font style="FONT-SIZE: 9pt">想想现在的计算机科班毕业生的水平吧，大学四年下来，</font></font><font style="FONT-SIZE: 9pt">90%</font><font face="宋体 "><font style="FONT-SIZE: 9pt">的学生写的代码没有超过</font></font><font style="FONT-SIZE: 9pt">2000</font><font face="宋体 "><font style="FONT-SIZE: 9pt">行，不</font></font><font style="FONT-SIZE: 9pt">Linux</font><font face="宋体 "><font style="FONT-SIZE: 9pt">操作系统为何物，不知道</font></font><font style="FONT-SIZE: 9pt">C++</font><font face="宋体 "><font style="FONT-SIZE: 9pt">和</font></font><font style="FONT-SIZE: 9pt">Vc</font><font face="宋体 "><font style="FONT-SIZE: 9pt">的区别，没有开发出一块实用功能的简单软件，</font></font> <font face="宋体 "><font style="FONT-SIZE: 9pt">没有使用过</font></font><font style="FONT-SIZE: 9pt">STL</font><font face="宋体 "><font style="FONT-SIZE: 9pt">，甚至不知</font></font><font style="FONT-SIZE: 9pt">STL</font><font face="宋体 "><font style="FONT-SIZE: 9pt">为何物，更不用提设计模式之类的比较高级一点的东西了</font></font><font style="FONT-SIZE: 9pt">&#8230;&#8230;</font><font face="宋体 "><font style="FONT-SIZE: 9pt">这样的例子还能举出很多</font></font><font style="FONT-SIZE: 9pt">&#8230;</font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">就是这样的人才质量，如何让一个以营利为目的的公司接受，如何为企业创造价值？</font></font> <font face="宋体 "><font style="FONT-SIZE: 9pt">但是也有那么一些人，能进入微软、</font></font><font style="FONT-SIZE: 9pt">IBM</font><font face="宋体 "><font style="FONT-SIZE: 9pt">、</font></font><font style="FONT-SIZE: 9pt">google</font><font face="宋体 "><font style="FONT-SIZE: 9pt">、百度这样的公司，拿着年薪几十万。</font></font><br><br><strong><font style="FONT-SIZE: 9pt">2. </font></strong><strong><font face="宋体 "><font style="FONT-SIZE: 9pt">失败的计算机教育体制</font></font></strong><br><font face="宋体 "><font style="FONT-SIZE: 9pt">我也是一名毕业不久的计算机科班毕业生，从我目前了解的情况看来，大学时，没有几个学生真正的对计算机编程感兴趣，体会不到通过编程解决问题带来的乐趣</font></font><font style="FONT-SIZE: 9pt">,</font><font face="宋体 "><font style="FONT-SIZE: 9pt">只是单纯的跟着课程的设置学习，这样没有目的性的学习效率如何之底？大学里的学生又有几个人能对自己的职业规划有一个基本的了解？大学里有几个人能理解学习的课程在具体的实践中的作用？</font></font> <font face="宋体 "><font style="FONT-SIZE: 9pt">这些惨痛的例子说明了我们大学对计算机系学生的引导是非常不够的？没能激起对学习计算机技术的兴趣？不能告诉大家一个将来一个明确的职业规划方向，没有很好的引导学生去思考自己的职业规划方向？如果是这种状态去学习，大学四年基本是废掉了</font></font><font style="FONT-SIZE: 9pt">&#8230;&#8230;</font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">另外一个就是大学课程的设置，各种各样的课程，填鸭式的教学方式</font></font><font style="FONT-SIZE: 9pt">&#8230;. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">纯粹理论式的教学方式</font></font><font style="FONT-SIZE: 9pt">&#8230;.</font><font face="宋体 "><font style="FONT-SIZE: 9pt">到头来，学生真正学到了什么？几个术语名词而已</font></font><font style="FONT-SIZE: 9pt">&#8230;..</font><font face="宋体 "><font style="FONT-SIZE: 9pt">一样对操作系统是那样的迷茫</font></font><font style="FONT-SIZE: 9pt">&#8230;.</font><font face="宋体 "><font style="FONT-SIZE: 9pt">不知道编译原理的语法分析为何物？</font></font> <font face="宋体 "><font style="FONT-SIZE: 9pt">不知道数据结构中的树和图将有何用？</font></font><br><br><strong><font style="FONT-SIZE: 9pt">3. </font></strong><strong><font face="宋体 "><font style="FONT-SIZE: 9pt">四年后，我能骄傲的说我是计算机系的学生</font></font></strong><br><font face="宋体 "><font style="FONT-SIZE: 9pt">上面发了那么多的牢骚，其实都是有感而发</font></font><font style="FONT-SIZE: 9pt">&#8230;.</font><font face="宋体 "><font style="FONT-SIZE: 9pt">下面在结合自己的工作的感受具体谈谈计算机学生应该如何规划自己的大学四年</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">大一：</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">一个新兵蛋子，刚走进象牙塔的大门，什么都是新鲜的，不断听着学长们说着天书般的技术术语</font></font><font style="FONT-SIZE: 9pt">&#8230; </font><font face="宋体 "><font style="FONT-SIZE: 9pt">天天争论</font></font><font style="FONT-SIZE: 9pt">C++</font><font face="宋体 "><font style="FONT-SIZE: 9pt">和</font></font><font style="FONT-SIZE: 9pt">java</font><font face="宋体 "><font style="FONT-SIZE: 9pt">哪个好，</font></font><font style="FONT-SIZE: 9pt">.net</font><font face="宋体 "><font style="FONT-SIZE: 9pt">是否比</font></font><font style="FONT-SIZE: 9pt">Vc</font><font face="宋体 "><font style="FONT-SIZE: 9pt">更智能先进</font></font><font style="FONT-SIZE: 9pt">&#8230;. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">还有什么</font></font><font style="FONT-SIZE: 9pt">Asp.net &#8230;. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">一堆的技术摆在自己面前了</font></font><font style="FONT-SIZE: 9pt">&#8230;</font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">然后自己就糊涂了</font></font><font style="FONT-SIZE: 9pt">&#8230;.</font><font face="宋体 "><font style="FONT-SIZE: 9pt">去问学长吧</font></font><font style="FONT-SIZE: 9pt">&#8230;</font><font face="宋体 "><font style="FONT-SIZE: 9pt">学长告诉你</font></font><font style="FONT-SIZE: 9pt">..</font><font face="宋体 "><font style="FONT-SIZE: 9pt">好好学习</font></font><font style="FONT-SIZE: 9pt">java</font><font face="宋体 "><font style="FONT-SIZE: 9pt">吧</font></font><font style="FONT-SIZE: 9pt">&#8230;</font><font face="宋体 "><font style="FONT-SIZE: 9pt">将来有钱途</font></font><font style="FONT-SIZE: 9pt">&#8230;..</font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">其实大一，没必要学习各种新鲜的技术</font></font><font style="FONT-SIZE: 9pt">&#8230;..</font><font face="宋体 "><font style="FONT-SIZE: 9pt">把高等数学学好吧</font></font><font style="FONT-SIZE: 9pt">&#8230;.</font><font face="宋体 "><font style="FONT-SIZE: 9pt">这才是正事，是决定了着将来你是否能称为一个大牛还是一个编程语言的熟练操作工人的因素</font></font><font style="FONT-SIZE: 9pt">&#8230;. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">也许这时候的你还不知道高等数学有什么作用</font></font><font style="FONT-SIZE: 9pt">&#8230;</font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">但我要告诉你的是如果你的悟性高</font></font><font style="FONT-SIZE: 9pt">&#8230;. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">工作一两年也许就能体会到数学的做用</font></font><font style="FONT-SIZE: 9pt">&#8230;. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">学高数</font></font><font style="FONT-SIZE: 9pt">..</font><font face="宋体 "><font style="FONT-SIZE: 9pt">不是简简单单的学习微积分</font></font><font style="FONT-SIZE: 9pt">&#8230;. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">在掌握这些知识的时候</font></font><font style="FONT-SIZE: 9pt">&#8230;.</font><font face="宋体 "><font style="FONT-SIZE: 9pt">锻炼自己的逻辑思维</font></font><font style="FONT-SIZE: 9pt">&#8230;.. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">锻炼自己的思考问题解决问题的方法和能力。作用在将来一定大大的</font></font><font style="FONT-SIZE: 9pt">&#8230;.. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">等将来如果你涉足密码学</font></font><font style="FONT-SIZE: 9pt">&#8230;</font><font face="宋体 "><font style="FONT-SIZE: 9pt">你会发现各种积分方程和矩阵变化</font></font><font style="FONT-SIZE: 9pt">&#8230;. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">将来在计算一个算法的复杂性和证明算法的可靠性时，也离不开数学知识</font></font><font style="FONT-SIZE: 9pt">&#8230;. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">如果你涉足人工智能和语音识别，各种统计模型就会呈现在你面前。在你毕业找工作时，这个才是你和专业培训机构培训出来的学生的差异能力。这才是企业更看重的能力。如果你还有时间的话，学习</font></font><font style="FONT-SIZE: 9pt">C</font><font face="宋体 "><font style="FONT-SIZE: 9pt">语言</font></font><font style="FONT-SIZE: 9pt">&#8230; </font><font face="宋体 "><font style="FONT-SIZE: 9pt">但是不要再用谭浩强的书了</font></font><font style="FONT-SIZE: 9pt">&#8230;. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">看</font></font><br><font style="FONT-SIZE: 9pt">The C program langue </font><font face="宋体 "><font style="FONT-SIZE: 9pt">吧</font></font><font style="FONT-SIZE: 9pt">&#8230; </font><font face="宋体 "><font style="FONT-SIZE: 9pt">如果能真正领悟书中</font></font><font style="FONT-SIZE: 9pt">70%</font><font face="宋体 "><font style="FONT-SIZE: 9pt">的例子话，那就足够了</font></font><font style="FONT-SIZE: 9pt">. </font><font face="宋体 "><font style="FONT-SIZE: 9pt">如果能把这两门课程学到十分优秀，恭喜你，你已经成功了一半了</font></font><font style="FONT-SIZE: 9pt">&#8230;..</font><br><br><font face="宋体 "><font style="FONT-SIZE: 9pt">大二：</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">如果你在大一学习了</font></font><font style="FONT-SIZE: 9pt">C</font><font face="宋体 "><font style="FONT-SIZE: 9pt">之后，这个时候大学的课程就要涉及操作系统和数据结构、还有汇编语言了</font></font><font style="FONT-SIZE: 9pt">&#8230;&#8230; </font><font face="宋体 "><font style="FONT-SIZE: 9pt">这也是大二一定要学好的两门课了</font></font><font style="FONT-SIZE: 9pt">&#8230;&#8230;</font><font face="宋体 "><font style="FONT-SIZE: 9pt">大学的操作系统太失败了，上完课后，很多的学生不知道所云，更加感觉操作系统的神秘了，课程设计也就是什么银行家算法的，然后大家在网上一顿搜索，然后交给老师就算完事了</font></font><font style="FONT-SIZE: 9pt">&#8230;</font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">其实，我的建议是自己写一个操作系统内核，实现内存管理，进程管理和切换</font></font> <font face="宋体 "><font style="FONT-SIZE: 9pt">等一些基础的东西了就可以了，《自己动手写操作系统》就是很好的教材</font></font><font style="FONT-SIZE: 9pt">&#8230;&#8230; </font><font face="宋体 "><font style="FONT-SIZE: 9pt">如果还有时间，学习《</font></font><font style="FONT-SIZE: 9pt">Linux</font><font face="宋体 "><font style="FONT-SIZE: 9pt">内核设计与实现》，看看现实商用的操作系统是怎么实现的？</font></font> <font face="宋体 "><font style="FONT-SIZE: 9pt">当然最好和原码结合的一起看，效果最好。还有赵炯博士的</font></font> <font face="宋体 "><font style="FONT-SIZE: 9pt">&#8220;</font></font><font style="FONT-SIZE: 9pt">.012Linux</font><font face="宋体 "><font style="FONT-SIZE: 9pt">内核完全剖析&#8221;什么的。如果能仔细阅读，收获一定不少。当然还有数据结构，这个也是重中之中，这也是和非科班出身的学生的差别，关键是你学的好坏，这个的实践主要在</font></font><font style="FONT-SIZE: 9pt">ACM</font><font face="宋体 "><font style="FONT-SIZE: 9pt">上，当学习完数据结构后，最重要的是使用，不断的在</font></font><font style="FONT-SIZE: 9pt">Acm</font><font face="宋体 "><font style="FONT-SIZE: 9pt">上做各种各样的题目，不断的提升自己算法设计的能力。从大二开始，如果能坚持两年下来，那么一般的算法设计肯定是难不住的了，也许这时候高数打下的基础就会起作用了。</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">当毕业的时候，进入一家好的公司应该不是太难的事情了。再说说汇编语言，本质上这也是一门编程语言，可能刚入门的时候比较困难，但是程序写多了，和</font></font><font style="FONT-SIZE: 9pt">C</font><font face="宋体 "><font style="FONT-SIZE: 9pt">也没有差别了。我还想说一点，就是现在</font></font><font style="FONT-SIZE: 9pt">Windows</font><font face="宋体 "><font style="FONT-SIZE: 9pt">内核也逐步开放了，至少有很多的逆向的资源可以学习。如果对</font></font><font style="FONT-SIZE: 9pt">Windows</font><font face="宋体 "><font style="FONT-SIZE: 9pt">有兴趣，一样可以学习操作系统的实现原理。</font></font><br><br><font face="宋体 "><font style="FONT-SIZE: 9pt">大三：</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">离散数学和编译原理是个重头戏，离散数学虽然我现在还没体会到他的作用，但是和高数一样，这中内在的东西才是最重要的，代表着内功，如果没有学好，这些债迟早还要要还的。</font></font> <font face="宋体 "><font style="FONT-SIZE: 9pt">编译原理，学习完以后一样会让你云里雾里，整天做那些无聊的题目。还是说实践吧，网上有开源的</font></font><font style="FONT-SIZE: 9pt">C</font><font face="宋体 "><font style="FONT-SIZE: 9pt">编译器的源码，下载下来然后好好学习下，结合编译原理书中讲的东西，好好的消化一些这些知识，最后，自己如果能写出来一个</font></font><font style="FONT-SIZE: 9pt">C</font><font face="宋体 "><font style="FONT-SIZE: 9pt">编译器的话，那你的编译原理也就通过了。当然这个时候可以学习一些</font></font><font style="FONT-SIZE: 9pt">C++</font><font face="宋体 "><font style="FONT-SIZE: 9pt">或</font></font><font style="FONT-SIZE: 9pt">Java</font><font face="宋体 "><font style="FONT-SIZE: 9pt">之类语言，但是学到够平时用的就可以了，没有学非常深。选择一本教材学习两三个月就行了。</font></font><br><br><br><font face="宋体 "><font style="FONT-SIZE: 9pt">当然，这个时候，可能你的同学已经能做出来各种漂亮的网页，也可能熟练的使用</font></font><font style="FONT-SIZE: 9pt">MFC</font><font face="宋体 "><font style="FONT-SIZE: 9pt">类库做出各种各样的漂亮的软件，这些没什么，如果三年下来，如果你能够按照上面我写的那样坚持学习。也许他们用三年学习的这些东西，你用三个月就能熟练。</font></font><br><br><font face="宋体 "><font style="FONT-SIZE: 9pt">大四：</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">到了找工作的时候，如果你按照上面一步一个脚印的学习，我相信你会收到很多大公司的</font></font><font style="FONT-SIZE: 9pt">offer</font><font face="宋体 "><font style="FONT-SIZE: 9pt">。因为大公司更看重的是你的内功的深厚，而小公司才会看重那些花拳绣腿的技术。但是这个时候，千万不要忘记继续学习，很多的学生大四一年都浪费掉了，真实太可惜了，在前面三年的基础上，到了厚积薄发的时候了，</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">开始要思考自己的职业规划了，你要选择</font></font><font style="FONT-SIZE: 9pt">Linux</font><font face="宋体 "><font style="FONT-SIZE: 9pt">方向还是</font></font><font style="FONT-SIZE: 9pt">Windows</font><font face="宋体 "><font style="FONT-SIZE: 9pt">方向，要选择底层方向还是应用方向，</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">要选择网页方向还是桌面应用方向。是选择自然语言处理还是人工智能。这个时候你要选择自己的一个方向，当然你可以向你的导师求助，然后确定自己的发展方向，大四一年就可以专心的学习了。</font></font><br><br><br><strong><font style="FONT-SIZE: 9pt">4. </font></strong><strong><font face="宋体 "><font style="FONT-SIZE: 9pt">附上我认为计算机学习比较好辅助教材：</font></font></strong><br><br><font style="FONT-SIZE: 9pt">C</font><font face="宋体 "><font style="FONT-SIZE: 9pt">语言：</font></font><font style="FONT-SIZE: 9pt"> the C Program Language</font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">操作系统</font></font><font style="FONT-SIZE: 9pt">; </font><font face="宋体 "><font style="FONT-SIZE: 9pt">于渊：《自己动手写操作系统》</font></font><br><br><font face="宋体 "><font style="FONT-SIZE: 9pt">《</font></font><font style="FONT-SIZE: 9pt">Linux</font><font face="宋体 "><font style="FONT-SIZE: 9pt">内核设计与实现》</font></font><br><br><font face="宋体 "><font style="FONT-SIZE: 9pt">《</font></font><font style="FONT-SIZE: 9pt">Linux</font><font face="宋体 "><font style="FONT-SIZE: 9pt">内核完全剖析》</font></font><br><br><font face="宋体 "><font style="FONT-SIZE: 9pt">《</font></font><font style="FONT-SIZE: 9pt">Linux</font><font face="宋体 "><font style="FONT-SIZE: 9pt">内核情景分析》</font></font><br><br><font face="宋体 "><font style="FONT-SIZE: 9pt">《</font></font><font style="FONT-SIZE: 9pt">Windows</font><font face="宋体 "><font style="FONT-SIZE: 9pt">内核情景分析》</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">编译原理：</font></font> <font face="宋体 "><font style="FONT-SIZE: 9pt">龙书《编译原理》</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">汇编：</font></font><br><font face="宋体 "><font style="FONT-SIZE: 9pt">王爽</font></font><font face="宋体 "><font style="FONT-SIZE: 9pt">老师《汇编第二版》</font></font><br><br><strong><font style="FONT-SIZE: 9pt">5. </font></strong><strong><font face="宋体 "><font style="FONT-SIZE: 9pt">后记</font></font></strong><br><br><font face="宋体 "><font style="FONT-SIZE: 9pt">以上都是自己在工作后对大学四年的反思，可能很多人有不一样的看法，我没有任何异议。毕竟每个人经历是不一样的，但是如果你向想做真正的计算机科班出身的学生，学好上面介绍的课程吧。在以后的职业生涯中，你会终身受益的。当然上面很多的课程我没有提到，并不代表他们不需要学习，只是分量没有那么重而已。因为你还是要毕业的，每门功课还是要过的。</font></font><font style="FONT-SIZE: 9pt">zds</font><br><br><font face="宋体 "><font style="FONT-SIZE: 9pt">当然，我现在认为，计算机的本科四年真是一个打基础的四年，之后才是学习各种招式，如果基础打好了，招式的学习会事半功倍的。当进入公司后，一样要持续不断的学习，才能让你不断的进步。自己文采不好，写的比较乱，但都是肺腑之言，各位将就看吧。</font></font><br></p>
<img src ="http://www.cppblog.com/Onway/aggbug/132259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Onway/" target="_blank">Onway</a> 2010-11-03 09:22 <a href="http://www.cppblog.com/Onway/articles/132259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>熟悉C++标准库（转）</title><link>http://www.cppblog.com/Onway/articles/132257.html</link><dc:creator>Onway</dc:creator><author>Onway</author><pubDate>Wed, 03 Nov 2010 01:15:00 GMT</pubDate><guid>http://www.cppblog.com/Onway/articles/132257.html</guid><wfw:comment>http://www.cppblog.com/Onway/comments/132257.html</wfw:comment><comments>http://www.cppblog.com/Onway/articles/132257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Onway/comments/commentRss/132257.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Onway/services/trackbacks/132257.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 14pt">C++标准库非常大。在C++标准中，关于标准库的规格说明占了密密麻麻300多页，这还不包括标准C库，后者只是 "作为参考"包含在C++库中。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">当然，并非总是越大越好，但在现在的情况下，确实越大越好，因为大的库会包含大量的功能。标准库中的功能越多，开发自己的应用程序时能借助的功能就越多。C++库并非提供了一切（没有提供并发和图形用户接口的支持），但确实提供了很多。几乎任何事都可以求助于它。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">因为标准库中东西如此之多，你所选择的类名或函数名就很有可能和标准库中的某个名字相同。为了避免这种情况所造成的名字冲突，实际上标准库中的一切都被放在名字空间std中。但这带来了一个新问题。无数现有的C++代码都依赖于使用了多年的伪标准库中的功能，例如，声明在&lt;iostream.h&gt;，&lt;complex.h&gt;，&lt;limits.h&gt;等头文件中的功能。现有软件没有针对使用名字空间而进行设计，如果用std来包装标准库导致现有代码不能用，将是一种可耻行为。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">慑于被激怒的程序员会产生的破坏力，标准委员会决定为包装了std的那部分标准库构件创建新的头文件名。生成新头文件的方法仅仅是将现有C++头文件名中的 .h 去掉，方法本身不重要，正如最后产生的结果不一致也并不重要一样。所以&lt;iostream.h&gt;变成了&lt;iostream&gt;，&lt;complex.h&gt;变成了&lt;complex&gt;，等等。对于C头文件，采用同样的方法，但在每个名字前还要添加一个c。所以C的&lt;string.h&gt;变成了&lt;cstring&gt;，&lt;stdio.h&gt;变成了&lt;cstdio&gt;，等等。最后一点是，旧的C++头文件是官方所反对使用的（即明确列出不再支持），但旧的C头文件则没有（以保持对C的兼容性）。实际上，编译器制造商不会停止对客户现有软件提供支持，所以可以预计，旧的C++头文件在未来几年内还是会被支持。</p>
<p style="FONT-SIZE: 14pt">所以，实际来说，下面是C++头文件的现状：</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">&#183; 旧的C++头文件名如&lt;iostream.h&gt;将会继续被支持，尽管它们不在官方标准中。这些头文件的内容不在名字空间std中。</p>
<p style="FONT-SIZE: 14pt">&#183; 新的C++头文件如&lt;iostream&gt;包含的基本功能和对应的旧头文件相同，但头文件的内容在名字空间std中。（在标准化的过程中，库中有些部分的细节被修改了，所以旧头文件和新头文件中的实体不一定完全对应。）</p>
<p style="FONT-SIZE: 14pt">&#183; 标准C头文件如&lt;stdio.h&gt;继续被支持。头文件的内容不在std中。</p>
<p style="FONT-SIZE: 14pt">&#183; 具有C库功能的新C++头文件具有如&lt;cstdio&gt;这样的名字。它们提供的内容和相应的旧C头文件相同，只是内容在std中。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">所有这些初看有点怪，但不难习惯它。最大的挑战是把字符串头文件理清楚：&lt;string.h&gt;是旧的C头文件，对应的是基于char*的字符串处理函数；&lt;string&gt;是包装了std的C++头文件，对应的是新的string类；&lt;cstring&gt;是对应于旧C头文件的std版本。如果能掌握这些，其余的也就容易了。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">关于标准库，需要知道的第二点是，库中的一切几乎都是模板。iostream帮助你操作字符流，但什么是字符？是char吗？是wchar_t？是Unicode字符？一些其它的多字节字符？没有明显正确的答案，所以标准库让你去选。所有的流类（stream class）实际上是类模板，在实例化流类的时候指定字符类型。例如，标准库将cout类型定义为ostream，但ostream实际上是一个basic_ostream&lt;char&gt;类型定义（typedef ）。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">类似的考虑适用于标准库中其它大部分类。string不是类，它是类模板：类型参数限定了每个string类中的字符类型。complex不是类，它是类模板：类型参数限定了每个complex类中实数部分和虚数部分的类型。vector不是类，它是类模板。如此不停地进行下去。</p>
<p style="FONT-SIZE: 14pt">在标准库中无法避开模板，但如果只是习惯于和char类型的流和字符串打交道，通常可以忽略它们。这是因为，对这些组件的char实例，标准库都为它们定义了typedef，这样就可以在编程时继续使用cin，cout，cerr等对象，以及istream，ostream，string等类型，不必担心cin的真实类型是basic_istream&lt;char&gt;以及string的真实类型是basic_string&lt;char&gt;。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">标准库中很多组件的模板化和上面所建议的大不相同。再看看那个概念上似乎很直观的string。当然，可以基于 "它所包含的字符类型" 确定它的参数，但不同的字符集在细节上有不同，例如，特殊的文件结束字符，拷贝它们的数组的最有效方式，等等。这些特征在标准中被称为traits，它们在string实例中通过另外一个模板参数指定。此外，string对象要执行动态内存分配和释放，但完成这一任务有很多不同的方法。哪一个最好？选择：string模板有一个Allocator参数，Allocator类型的对象被用来分配和释放string对象所使用的内存。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">这里有一个basic_string模板的完整声明，以及建立在它之上的string类型定义（typedef）；可以在&lt;string&gt;头文件中找到它（或与之相当的什么东西）：</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">namespace std {</p>
<p style="FONT-SIZE: 14pt">&nbsp;&nbsp; template&lt;class charT,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class traits = char_traits&lt;charT&gt;,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Allocator = allocator&lt;charT&gt; &gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class basic_string;</p>
<p style="FONT-SIZE: 14pt">&nbsp;&nbsp; typedef basic_string&lt;char&gt; string;</p>
<p style="FONT-SIZE: 14pt">}</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">注意，basic_string的traits和Allocator参数有缺省值。这在标准库中是很典型的做法。它为使用者提供了灵活性，但对于这种灵活性所带来的复杂性，那些只想做 "正常" 操作的"典型" 用户却又可以避开。换句话说，如果只想使用象C字符串那样的字符串对象，就可以使用string对象，而不用在意实际上是在用basic_string&lt;char, char_traits&lt;char&gt;, allocator&lt;char&gt; &gt;类型的对象。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">通常可以这么做，但有时还是得稍稍看看底层。例如，声明一个类而不提供定义具有优点；它还指出，下面是一种声明string类型的错误方法：</p>
<p style="FONT-SIZE: 14pt">class string;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 会通过编译，</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">先不要考虑名字空间，这里真正的问题在于：string不是一个类，而是一个typedef。如果可以通过下面的方法解决问题就太好了：</p>
<p style="FONT-SIZE: 14pt">typedef basic_string&lt;char&gt; string;</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">但这又不能通过编译。"所说的basic_string是什么东西？" 编译器会奇怪 ---- 当然，它可能会用不同的语句来问你。所以，为了声明string，首先得声明它所依赖的所有模板。如果可以这么做的话，就会象下面这样：</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">template&lt;class charT&gt; struct char_traits;</p>
<p style="FONT-SIZE: 14pt">template&lt;class T&gt; class allocator;</p>
<p style="FONT-SIZE: 14pt">template&lt;class charT, class traits = char_traits&lt;charT&gt;,<br>class Allocator = allocator&lt;charT&gt; &gt;<br>class basic_string;</p>
<p style="FONT-SIZE: 14pt">typedef basic_string&lt;char&gt; string;</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">然而，你不能声明string。至少不应该。这是因为，标准库的实现者声明的stirng（或std名字空间中任何其它东西）可以和标准中所指定的有所不同，只要最终提供的行为符合标准就行。例如，basic_string的实现可以增加第四个模板参数，但这个参数的缺省值所产生的代码的行为要和标准中所说的原始的basic_string一致。那到底该怎么办？不要手工声明string（或标准库中其它任何部分）。相反，只用包含一个适当的头文件，如&lt;string&gt;。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">有了头文件和模板的这些知识，现在可以看看标准C++库中有哪些主要组件：</p>
<p style="FONT-SIZE: 14pt">&#183; 标准C库。它还在，还可以用它。虽然有些地方有点小的修修补补，但无论怎么说，还是那个用了多年的C库。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">&#183; Iostream。和 "传统" Iostream的实现相比，它已经被模板化了，继承层次结构也做了修改，增强了抛出异常的能力，可以支持string（通过stringstream类）和国际化（通过locales）。当然，你期望Iostream库所具有的东西几乎全都继续存在。也就是说，它还是支持流缓冲区，格式化标识符，操作子和文件，还有cin，cout，cerr和clog对象。这意味着可以把string和文件当做流，还可以对流的行为进行更广泛的控制，包括缓冲和格式化。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">&#183; String。string对象在大多数应用中被用来消除对char*指针的使用。它们支持你所期望的那些操作（例如，字符串连接，通过operator[]对单个字符进行常量时间级的访问，等等），它们可以转换成char*，以保持和现有代码的兼容性，它们还自动处理内存管理。一些string的实现采用了引用计数，这会带来比基于char*的字符串更佳的性能（时间和空间上）。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">&#183; 容器。标准库提供了高效的容器实现：vector（就象动态可扩充的数组），list（双链表），queue， stack，deque，map，set和bitset。但多少可以作为补偿的一点是， string是容器。这很重要，因为它意味着对容器所做的任何操作对string也适用。</p>
<p style="FONT-SIZE: 14pt">标准库规定了每个类的接口，而且每条接口规范中的一部分是一套性能保证。所以，举例来说，无论vector是如何实现的，仅仅提供对它的元素的访问是不够的，还必须提供 "常量时间" 内的访问。如果不这样，就不是一个有效的vector实现。</p>
<p style="FONT-SIZE: 14pt">很多C++程序中，动态分配字符串和数组导致大量使用new和delete，new/delete错误 ---- 尤其是没有delete掉new出来的内存而导致的泄漏 ---- 时常发生。如果使用string和vector对象（二者都执行自身的内存管理）而不使用char*和动态分配的数组的指针，很多new和delete就可以免于使用，使用它们所带来的问题也会随之消失。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">&#183; 算法。标准库就提供了大量简易的方法（即，预定义函数，官方称为算法(algorithm) ---- 实际上是函数模板），其中的大多数适用于库中所有的容器 ---- 以及内建数组（built-in arrays）。</p>
<p style="FONT-SIZE: 14pt">算法将容器的内容当作序列（sequence），每个算法可以应用于一个容器中所有值所对应的序列，或者一个子序列（subsequence）。标准算法有for_each（为序列中的每个元素调用某个函数），find（在序列中查找包含某个值的第一个位置，count_if（计算序列中使得某个判定为真的所有元素的数量），equal（确定两个序列包含的元素的值是否完全相同），search（在一个序列中找出某个子序列的起始位置），copy（拷贝一个序列到另一个），unique（在序列中删除重复值），rotate（旋转序列中的值），sort（对序列中的值排序）。注意这里只是抽取了所有算法中的几个；标准库中还包括其它很多算法。</p>
<p style="FONT-SIZE: 14pt">和容器操作一样，算法也有性能保证。例如，stable_sort算法执行时要求不超过0比较级(N log N) 。（stable_sort提供的性能必须和最高效的通用排序算法在同一个级别。）</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">&#183; 对国际化的支持。不同的文化以不同的方式行事。和C库一样，C++库提供了很多特性有助于开发出国际化的软件。但虽然从概念上来说和C类似，其实C++的方法还是有所不同。例如，C++为支持国际化广泛使用了模板，还利用了继承和虚函数，这些一定不会让你感到奇怪。</p>
<p style="FONT-SIZE: 14pt">支持国际化最主要的构件是facets和locales。facets描述的是对一种文化要处理哪些特性，包括排序规则（即，某地区字符集中的字符应该如何排序），日期和时间应该如何表示，数字和货币值应该如何表示，怎样将信息标识符映射成（自然的）明确的语言信息，等等。locales将多组facets捆绑在一起。例如，一个关于美国的locale将包括很多facets，描述如何对美国英语字符串排序，如何以适合美国人的方式读写日期和时间，读写货币和数字值，等等。而对于一个关于法国的locales来说，它描述的是怎么以法国人所习惯的方式完成这些任务。C++允许单个程序中同时存在多个locales，所以一个应用中的不同部分可能采用的是不同的规范。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">&#183; 对数字处理的支持。C++库为复数类（实数和虚数部分的精度可以是float，double或long double）和专门针对数值编程而设计的特殊数组提供了模板。例如，valarray类型的对象可用来保存可以任意混叠(aliasing)的元素。这使得编译器可以更充分地进行优化，尤其是对矢量计算机来说。标准库还对两种不同类型的数组片提供了支持，并提供了算法计算内积(inner product)，部分和(partial sum)，临差(adjacent difference)等。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">&#183; 诊断支持。标准库支持三种报错方式：C的断言，错误号，例外。为了有助于为例外类型提供某种结构，标准库定义了下面的例外类（exception class）层次结构：</p>
<p style="FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |---domain_error<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |----- logic_error&lt;---- |---invalid_argument<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |---length_error<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |---out_of_range<br>exception&lt;--|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |--- range_error<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-----runtime_error&lt;--|---underflow_error<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |---overflow_error</p>
<p style="FONT-SIZE: 14pt">logic_error（或它的子类）类型的例外表示的是软件中的逻辑错误。理论上来说，这样的错误可以通过更仔细的程序设计来防止。runtime_error（或它的子类）类型的例外表示的是只有在运行时才能发现的错误。</p>
<p style="FONT-SIZE: 14pt">可以就这样使用它们，可以通过继承它们来创建自己的例外类，或者可以不去管它。没有人强迫你使用它。</p>
<p style="FONT-SIZE: 14pt">上面列出的内容并没有涵盖标准库中的一切。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">标准库中容器和算法这部分一般称为标准模板库。STL中实际上还有第三个构件 ---- 迭代子（Iterator）。迭代子是指针似的对象，它让STL算法和容器共同工作。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">STL是标准库中最具创新的部分，这并不是因为它提供了容器和算法（虽然它们非常有用），而是因为它的体系结构。简单来说，它的体系结构具有扩展性：可以对STL进行添加。当然，标准库中的组件本身是固定的，但如果遵循STL构建的规范，可以写出自己的容器，算法和迭代子，使它们可以和标准STL组件一起工作，就象标准组件自身之间相互工作一样。还可以利用别人所写的符合STL规范的容器，算法和迭代子，就象别人利用你的一样。使得STL具有创新意义的原因在于它实际上不是软件，而是一套规范（convention）。标准库中的STL组件只是具体体现了遵循这种规范所能带来的好处。</p>
<p style="FONT-SIZE: 14pt">&nbsp;</p>
<p style="FONT-SIZE: 14pt">通过使用标准库中的组件，通常可以避免从头到尾来设计自己的IO流，string，容器，国际化，数值数据结构以及诊断等机制。这就有更多的时间和精力去关注软件开发中真正重要的部分：实现软件的其他功能。<br><br><br>转自：<a href="http://hi.baidu.com/why0813/blog/item/850ea46eecf658db80cb4a6a.html">http://hi.baidu.com/why0813/blog/item/850ea46eecf658db80cb4a6a.html</a></p>
<img src ="http://www.cppblog.com/Onway/aggbug/132257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Onway/" target="_blank">Onway</a> 2010-11-03 09:15 <a href="http://www.cppblog.com/Onway/articles/132257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>max()函数</title><link>http://www.cppblog.com/Onway/articles/121710.html</link><dc:creator>Onway</dc:creator><author>Onway</author><pubDate>Fri, 30 Jul 2010 09:09:00 GMT</pubDate><guid>http://www.cppblog.com/Onway/articles/121710.html</guid><wfw:comment>http://www.cppblog.com/Onway/comments/121710.html</wfw:comment><comments>http://www.cppblog.com/Onway/articles/121710.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Onway/comments/commentRss/121710.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Onway/services/trackbacks/121710.html</trackback:ping><description><![CDATA[<span class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium Simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span class=Apple-style-span style="FONT-SIZE: 14px; LINE-HEIGHT: 23px; FONT-FAMILY: simsun; TEXT-ALIGN: left">首先,max()在标准C++中的确是个函数而非宏.它在不同编译系统中的实际定义如下:<span class=Apple-converted-space>&nbsp;</span><br>===========================================================<span class=Apple-converted-space>&nbsp;</span><br>linux &nbsp; 下的 &nbsp; g++,头文件 &lt;algorithm&gt;<span class=Apple-converted-space>&nbsp;</span><br>template &nbsp; &lt;class &nbsp; _Tp&gt;<span class=Apple-converted-space>&nbsp;</span><br>inline &nbsp; const &nbsp; _Tp&amp; &nbsp; max(const &nbsp; _Tp&amp; &nbsp; __a, &nbsp; const &nbsp; _Tp&amp; &nbsp; __b) &nbsp; {<span class=Apple-converted-space>&nbsp;</span><br>&nbsp; &nbsp; return &nbsp; &nbsp; __a &nbsp; &lt; &nbsp; __b &nbsp; ? &nbsp; __b &nbsp; : &nbsp; __a;<span class=Apple-converted-space>&nbsp;</span><br>}<span class=Apple-converted-space>&nbsp;</span><br>===========================================================<span class=Apple-converted-space>&nbsp;</span><br>windows &nbsp; 下的 &nbsp; VC6,头文件 &lt;algorithm&gt; &nbsp; (最新的VS.net没试过,不敢妄言)<span class=Apple-converted-space>&nbsp;</span><br>template &lt;class &nbsp; _Ty&gt; &nbsp; inline<span class=Apple-converted-space>&nbsp;</span><br>const &nbsp; _Ty&amp; &nbsp; _cpp_max(const &nbsp; _Ty&amp; &nbsp; _X, &nbsp; const &nbsp; _Ty&amp; &nbsp; _Y)<span class=Apple-converted-space>&nbsp;</span><br>{return &nbsp; (_X &nbsp; &lt; &nbsp; _Y &nbsp; ? &nbsp; _Y &nbsp; : &nbsp; _X); &nbsp; }<span class=Apple-converted-space>&nbsp;</span><br>===========================================================<span class=Apple-converted-space>&nbsp;</span><br><br>看到了吗? &nbsp; g++按照标准C++的规定把它定义为max();而VC6自作主张把它变成了_cpp_max().<span class=Apple-converted-space>&nbsp;</span><br>事实上,我提问时所附的源代码是符合标准C++规则的,在g++下顺利编译,而由于VC6把max()变成_cpp_max(),导致无法编译.<span class=Apple-converted-space>&nbsp;</span><br><br>要在VC6用max(),只能退而求其次使用_cpp_max().或_MAX().<span class=Apple-converted-space>&nbsp;</span><br>因为在头文件algorithm包含的另一个头文件xutility里有一句 &nbsp; #define &nbsp; _MAX &nbsp; _cpp_max<span class=Apple-converted-space>&nbsp;</span><br><br>另外有一个相关的宏__max, &nbsp; 是定义在stdlib.h中的:#define &nbsp; __max(a,b) &nbsp; (((a) &nbsp; &gt; &nbsp; (b)) &nbsp; ? &nbsp; (a) &nbsp; : &nbsp; (b)),不过__max不是标准C++,是以前的C留下来的.<span class=Apple-converted-space>&nbsp;<br><br>引用自CSDN</span></span></span>
<img src ="http://www.cppblog.com/Onway/aggbug/121710.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Onway/" target="_blank">Onway</a> 2010-07-30 17:09 <a href="http://www.cppblog.com/Onway/articles/121710.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACM训练之道</title><link>http://www.cppblog.com/Onway/articles/101248.html</link><dc:creator>Onway</dc:creator><author>Onway</author><pubDate>Tue, 17 Nov 2009 13:28:00 GMT</pubDate><guid>http://www.cppblog.com/Onway/articles/101248.html</guid><description><![CDATA[<div class=postText>摘自某位大牛的，于我，路漫漫啊&#8230;&#8230;<br>
<p><br><br><br><span style="FONT-SIZE: 18pt">相信每一位玩ACM程序设计竞赛的同学来说，都有一个从入门到精通的过程，而且分享他们经验的时候，见到最多的就是一种合作和拼搏精神，乐在其中的那种激情。</span> </p>
<p style="FONT-SIZE: 18pt">&nbsp;　　Wilbert即将毕业，作为一个菜鸟级的入门玩家，一直很想知道如何能在程序设计竞赛中成为一个高手。即将无缘类似竞赛的我，终于整理出了一些程序设计竞赛ACM训练之道，愿与大家分享。 </p>
<p style="FONT-SIZE: 18pt">&nbsp;　　首先是编程的能力，一般要做到50行以内的程序不用调试、100行以内的二分钟内调试成功。 </p>
<p style="FONT-SIZE: 18pt">&nbsp;　　训练过ACM等程序设计竞赛的人在算法上有较大的优势，这就说明当你编程能力提高之后，主要时间是花在思考算法上，不是花在写程序与debug上。 </p>
<p style="FONT-SIZE: 18pt">&nbsp;我摘录了网上的一个 训练计划 ： </p>
<p style="FONT-SIZE: 18pt">&nbsp;第一阶段： 练经典常用算法，下面的每个算法给我打上十到二十遍，同时自己精简代码，因为太常用，所以要练到写时不用想，10-15分钟内打完。&nbsp;&nbsp;&nbsp; </p>
<p style="FONT-SIZE: 18pt">1．最短路（Floyd、Dijstra、BellmanFord）； </p>
<p style="FONT-SIZE: 18pt">2．最小生成树（先写个prim，kruscal要用并查集，不好写）； </p>
<p style="FONT-SIZE: 18pt">3．大数（高精度）加减乘除；</p>
<p style="FONT-SIZE: 18pt">4．二分查找（代码可在五行以内）； </p>
<p style="FONT-SIZE: 18pt">5．叉乘、判线段相交、然后写个凸包；</p>
<p style="FONT-SIZE: 18pt">6．BFS、DFS，同时熟练hash表（要熟，要灵活,代码要简）；</p>
<p style="FONT-SIZE: 18pt">7．数学上的有：辗转相除（两行内），线段交点、多角形面积公式；</p>
<p style="FONT-SIZE: 18pt">8．调用系统的qsort, 技巧很多，慢慢掌握；</p>
<p style="FONT-SIZE: 18pt">9．任意进制间的转换......</p>
<p style="FONT-SIZE: 18pt">&nbsp;</p>
<p style="FONT-SIZE: 18pt">第二阶段： 练习复杂一点，但也较常用的算法。 如：&nbsp;&nbsp;&nbsp; </p>
<p style="FONT-SIZE: 18pt">1．二分图匹配（匈牙利），最小路径覆盖；</p>
<p style="FONT-SIZE: 18pt">2．网络流，最小费用流；</p>
<p style="FONT-SIZE: 18pt">3．线段树；</p>
<p style="FONT-SIZE: 18pt">4. 并查集；&nbsp;&nbsp;&nbsp; </p>
<p style="FONT-SIZE: 18pt">5．熟悉动态规划的各个典型：LCS、最长递增子串、三角剖分、记忆化dp&nbsp;&nbsp;&nbsp; ；</p>
<p style="FONT-SIZE: 18pt">6．博弈类算法。博弈树，二进制法等；</p>
<p style="FONT-SIZE: 18pt">7．最大团，最大独立集；</p>
<p style="FONT-SIZE: 18pt">　　8．判断点在多边形内；</p>
<p style="FONT-SIZE: 18pt">9．差分约束系统；&nbsp;&nbsp;&nbsp; </p>
<p style="FONT-SIZE: 18pt">10．双向广度搜索、A*算法，最小耗散优先...... </p>
<p style="FONT-SIZE: 18pt">&nbsp;算法书 有很多可以参考： </p>
<p style="FONT-SIZE: 18pt">&nbsp;1、Concrete Mathematics --- A Foundation For Computer Science</p>
<p style="FONT-SIZE: 18pt">Ronald L. Graham ， Donald E. Knuth ， Oren Patashnik</p>
<p style="FONT-SIZE: 18pt">这本书《具体数学》是Stanford计算机系的教材（1970 年开始给研究生授课），书的内容是Knuth的巨著TAOCP第一章的扩展，涉及了计算机科学领域内几乎所有可能遇到的数学知识。书中许多经典问题的解答 比目前广泛流传的解法更易懂。对于提高大家的数学修养有很大帮助。 </p>
<p style="FONT-SIZE: 18pt">&nbsp;</p>
<p style="FONT-SIZE: 18pt">2、Introduction to Algorithms</p>
<p style="FONT-SIZE: 18pt">Thomas H. Cormen ，Charles E. Leiserson ，Ronald L. Rivest ，Clifford Stein</p>
<p style="FONT-SIZE: 18pt">《算法导论》MIT计算机系的经典算法教材。作者Rivest获得过ACM Turing Award，牛！本书内容全面，语言通俗，很适合大家入门。 </p>
<p style="FONT-SIZE: 18pt">&nbsp;</p>
<p style="FONT-SIZE: 18pt">3、实用算法的分析和程序设计</p>
<p style="FONT-SIZE: 18pt">吴文虎 王建德</p>
<p style="FONT-SIZE: 18pt">大名鼎鼎的&#8220;黑书&#8221;。内容包括了竞赛需要的各种算法，各种层次的读者都适合。 </p>
<p style="FONT-SIZE: 18pt">&nbsp;</p>
<p style="FONT-SIZE: 18pt">4、网络算法与复杂性理论</p>
<p style="FONT-SIZE: 18pt">谢政 李建平</p>
<p style="FONT-SIZE: 18pt">内容很丰富的图论教材 </p>
<p style="FONT-SIZE: 18pt">&nbsp;</p>
<p style="FONT-SIZE: 18pt">5、算法+数据结构=程序</p>
<p style="FONT-SIZE: 18pt">N.Wirth</p>
<p style="FONT-SIZE: 18pt">Pascal语言的发明人Wirth教授的名著，深入阐述了算法与数据结构的关系，对每个算法都提供详细的Pascal源程序，适合各种水平的读者。 </p>
<p style="FONT-SIZE: 18pt">&nbsp;　　最后，在学习算法提升战斗力的同时，也要多做题目，实战是很有必要的。其实并不是所有的题目都是靠算法的，有一些题目是有多种可以优化的手段，也有一些工程性比较强的题目。上手做和把题做精还是有很大区别的（惭愧的说，我就是属于上手做，没有做精，所以&#8230;&#8230;）。 </p>
<p style="FONT-SIZE: 18pt">&nbsp;　　愿每一位程序设计竞赛爱好者挑战极限！</p>
</div>
<img src ="http://www.cppblog.com/Onway/aggbug/101248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Onway/" target="_blank">Onway</a> 2009-11-17 21:28 <a href="http://www.cppblog.com/Onway/articles/101248.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>