




已阅读5页,还剩73页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
动态规划入门1(2008-09-20 21:40:51) 第一节 动态规划基本概念一,动态规划三要素:阶段,状态,决策。 他们的概念到处都是,我就不多说了,我只说说我对他们的理解:如果把动态规划的求解过程看成一个工厂的生产线,阶段就是生产某个商品的不同的环节,状态就是工件当前的形态,决策就是对工件的操作。显然不同阶段是对产品的一个前面各个状态的小结,有一个个的小结构成了最终的整个生产线。每个状态间又有关联(下一个状态是由上一个状态做了某个决策后产生的)。下面举个例子: 要生产一批雪糕,在这个过程中要分好多环节:购买牛奶,对牛奶提纯处理,放入工厂加工,加工后的商品要包装,包装后就去销售,这样没个环节就可以看做是一个阶段;产品在不同的时候有不同的状态,刚开始时只是白白的牛奶,进入生产后做成了各种造型,从冷冻库拿出来后就变成雪糕(由液态变成固态=_=|)。每个形态就是一个状态,那从液态变成固态经过了冰冻这一操作,这个操作就是一个决策。一个状态经过一个决策变成了另外一个状态,这个过程就是状态转移,用来描述状态转移的方程就是状态转移方程。 经过这个例子相信大家对动态规划有所了解了吧。下面在说说我对动态规划的另外一个理解:用图论知识理解动态规划:把动态规划中的状态抽象成一个点,在有直接关联的状态间连一条有向边,状态转移的代价就是边上的权。这样就形成了一个有向无环图AOE网(为什么无环呢?往下看)。对这个图进行拓扑排序,删除一个边后同时出现入度为0的状态在同一阶段。这样对图求最优路径就是动态规划问题的求解。二,动态规划的适用范围 动态规划用于解决多阶段决策最优化问题,但是不是所有的最优化问题都可以用动态规划解答呢?一般在题目中出现求最优解的问题就要考虑动态规划了,但是否可以用还要满足两个条件:最优子结构(最优化原理) 无后效性 最优化原理在下面的最短路径问题中有详细的解答;什么是无后效性呢?就是说在状态i求解时用到状态j而状态j就解有用到状态k.状态N。而求状态N时有用到了状态i这样求解状态的过程形成了环就没法用动态规划解答了,这也是上面用图论理解动态规划中形成的图无环的原因。 也就是说当前状态是前面状态的完美总结,现在与过去无关。当然,有是换一个划分状态或阶段的方法就满足无后效性了,这样的问题仍然可以用动态规划解。三,动态规划解决问题的一般思路。 拿到多阶段决策最优化问题后,第一步要判断这个问题是否可以用动态规划解决,如果不能就要考虑搜索或贪心了。当却定问题可以用动态规划后,就要用下面介绍的方法解决问题了:(1)模型匹配法: 最先考虑的就是这个方法了。挖掘问题的本质,如果发现问题是自己熟悉的某个基本的模型,就直接套用,但要小心其中的一些小的变动,现在考题办都是基本模型的变形套用时要小心条件,三思而后行。这些基本模型在先面的分类中将一一介绍。(2)三要素法仔细分析问题尝试着确定动态规划的三要素,不同问题的却定方向不同:先确定阶段的问题:数塔问题,和走路问题(详见解题报告)先确定状态的问题:大多数都是先确定状态的。先确定决策的问题:背包问题。(详见解题报告)一般都是先从比较明显的地方入手,至于怎么知道哪个明显就是经验问题了,多做题就会发现。(3)寻找规律法:这个方法很简单,耐心推几组数据后,看他们的规律,总结规律间的共性,有点贪心的意思。(4)边界条件法 找到问题的边界条件,然后考虑边界条件与它的领接状态之间的关系。这个方法也很起效。(5)放宽约束和增加约束 这个思想是在陈启锋的论文里看到的,具体内容就是给问题增加一些条件或删除一些条件使问题变的清晰。 第二节 动态规划分类讨论这里用状态维数对动态规划进行了分类:1.状态是一维的11下降/非降子序列问题:问题描述: 挖掘题目的本质,一但抽象成这样的描述就可以用这个方法解在一个无序的序列a1,a2,a3,a4an里,找到一个最长的序列满足:ai=aj=ak=am,且ijkajakam,且ijkm.(最长下降子序列)。问题分析:如果前i-1个数中用到ak (akai或akai(或aj=ai),optj+1就是opti的值;用方程表示为:我习惯了这种写法,但不是状态转移方程的标准写法 opti=max(optj)+1 (0=ji 且aj=ai) 最长非降子序列opti=max(optj)+1 (0=jai) 最长下降子序列实现求解的部分代码: opt0:=maxsize;maxsize 为maxlongint或-maxlongintfor i:=1 to n dofor j:=0 to i-1 doif ( ajai) and (optj+1opti) then opti:=optj+1;ans:=-maxlongint;for i:=1 to n doif optians then ans:=opti; ans 为最终解复杂度:从上面的实现不难看出时间复杂度为O(N2),空间复杂度O(N);例题1拦截导弹(missile.pas/c/cpp)来源:NOIP1999(提高组) 第一题【问题描述】 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。 输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。【输入文件】missile.in 单独一行列出导弹依次飞来的高度。【输出文件】missile.out 两行,分别是最多能拦截的导弹数,要拦截所有导弹最少要配备的系统数【输入样例】389 207 155 300 299 170 158 65【输出样例】62【问题分析】有经验的选手不难看出这是一个求最长非升子序列问题,显然标准算法是动态规划。以导弹依次飞来的顺序为阶段,设计状态opti表示前i个导弹中拦截了导弹i可以拦截最多能拦截到的导弹的个数。状态转移方程:opti=max(optj)+1 (hi=hj,0=j=ai) and (optj+1opti) then opti:=optj+1; anslen:=0; for i:=1 to n do if optianslen then anslen:=opti; fillchar(opt,sizeof(opt),0); a0:=-maxlongint; for i:=1 to n do for j:=i-1 downto 0 do if (ajopti) then opti:=optj+1; anstime:=0; for i:=1 to n do if optianstime then anstime:=opti;end;procedure print;begin writeln(anslen); writeln(anstime); close(input); close(output);end;begininit;main;print;end. 例题二合唱队形(chorus.pas/c/cpp)来源:NOIP2004(提高组) 第一题 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,K,他们的身高分别为T1,T2,TK,则他们的身高满足T1.Ti+1TK(1=i=K)。你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。【输入文件】输入文件chorus.in的第一行是一个整数N(2=N=100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130=Ti=230)是第i位同学的身高(厘米)。【输出文件】输出文件chorus.out包括一行,这一行只包含一个整数,就是最少需要几位同学出列。【样例输入】8186 186 150 200 160 130 197 220【样例输出】4【数据规模】对于50的数据,保证有n=20;对于全部的数据,保证有n=100。【问题分析】 出列人数最少,也就是说留的人最多,也就是序列最长。这样分析就是典型的最长下降子序列问题。只要枚举每一个人站中间时可以的到的最优解。显然它就等于,包括他在内向左求最长上升子序列,向右求最长下降子序列。我们看一下复杂度:计算最长下降子序列的复杂度是O(N2),一共求N次,总复杂度是O(N3)。这样的复杂度对于这个题的数据范围来说是可以AC的。但有没有更好的方法呢?其实最长子序列只要一次就可以了。因为最长下降(上升)子序列不受中间人的影响。只要用OPT1求一次最长上升子序列,OPT2求一次最长下降子序列。这样答案就是N-max(opt1i+opt2i-1).复杂度由O(N3)降到了O(N2)。【源代码】program chorus;constfin=chorus.in;fout=chorus.out;maxn=200;varopt1,opt2,a:array0.maxn of longint;n,ans:longint;procedure init;var i:longint;begin assign(input,fin); reset(input); assign(output,fout); rewrite(output); readln(n); for i:=1 to n do read(ai);end;procedure main;var i,j:longint;begin a0:=-maxlongint; for i:=1 to n do for j:=i-1 downto 0 do if (ajopt1i) then opt1i:=opt1j+1; an+1:=-maxlongint; for i:=n downto 1 do for j:=i+1 to n+1 do if (ajopt2i) then opt2i:=opt2j+1; ans:=0; for i:=1 to n do if opt1i+opt2ians then ans:=opt1i+opt2i;end;procedure print;begin writeln(n-ans+1); close(input); close(output);end;begininit;main;print;end. 例题3Buy Low Buy Lower(buylow.pas/c/cpp) 来源: USACO 4-3-1【问题描述】 “逢低吸纳”是炒股的一条成功秘诀。如果你想成为一个成功的投资者,就要遵守这条秘诀:逢低吸纳,越低越买这句话的意思是:每次你购买股票时的股价一定要比你上次购买时的股价低.按照这个规则购买股票的次数越多越好,看看你最多能按这个规则买几次。给定连续的N天中每天的股价。你可以在任何一天购买一次股票,但是购买时的股价一定要比你上次购买时的股价低。写一个程序,求出最多能买几次股票。以下面这个表为例, 某几天的股价是:天数 1 2 3 4 5 6 7 8 9 10 11 12 股价 68 69 54 64 68 64 70 67 78 62 98 87 这个例子中, 聪明的投资者(按上面的定义),如果每次买股票时的股价都比上一次买时低,那么他最多能买4次股票。一种买法如下(可能有其他的买法):天数 2 5 6 10 股价 69 68 64 62 【输入文件】buylow.in第1行: N (1 = N =aj,0=ji) ai存第i天股价最大的opti就是最终的解。第二问呢,稍麻烦一点。从问题的边界出发考虑问题,当第一问求得一个最优解opti=X时,在1到N中如果还有另外一个optj=x那么选取J的这个方案肯定是成立的。是不是统计所有的optj=x 的个数就是解了呢?显然没那么简单,因为选取这天的股票构成的方案不见得,看下面一个例子:6 43 2方案一:方案二:方案三:方案四:x=4也就是所虽然opt5=X 和opt6=X但个数只有两个,而实际上应该有四个方案,但在仔细观察发现,构成opt5=x 的这个方案中 optj=x-1的方案数有两个,optj=x-2的有一个,optj=x-3 的有一个显然这是满足低归定义的设计函数F(i)表示前I张中用到第i张股票的方案数。递推式: 1 (i=0)F(i)= Sum(F(j) (0=jai,optj=opti-1) sum 代表求和答案=sum(F(j) 0jai) and (optj+1opti) then opti:=optj+1;for i:=1 to n do begin j:=i-1; while (j0) and (optioptj) or (aiaj) do dec(j); nexti:=j; end; F0,1:=1; for i:=1 to n+1 do for j:=i-1 downto nexti do if (optj=opti-1) and (ajai) then Hinc(Fi,Fj);end;procedure print;var i,top,m:longint;begin write(optn+1-1, ); top:=maxsize; while (top1) and (Fn+1top=0) do dec(top); write(Fn+1,top); for i:=top-1 downto 1 do begin m:=Fn+1,i; while mmaxsize div 10 do begin write(0); m:=m*10; end; write(Fn+1,i); end; writeln; close(input); close(output);end;begininit;main;print;end. 例题4船(ships.pas/c/cpp) 来源:奥赛经典(提高篇)【问题描述】PALMIA国家被一条河流分成南北两岸,南北两岸上各有N个村庄。北岸的每一个村庄有一个唯一的朋友在南岸,且他们的朋友村庄彼此不同。每一对朋友村庄想要一条船来连接他们,他们向政府提出申请以获得批准。由于河面上常常有雾,政府决定禁止船只航线相交(如果相交,则很可能导致碰船)。你的任务是编写一个程序,帮助政府官员决定批准哪些船只航线,使得不相交的航线数目最大。【输入文件】ships.in 输入文件由几组数据组成。每组数据的第一行有2个整数X,Y,中间有一个空格隔开,X代表PALMIA河的长度(10=X=6000),Y代表河的宽度(10=Y=100)。第二行包含整数N,表示分别坐落在南北两岸上的村庄的数目(1=N=5000)。在接下来的N行中,每一行有两个非负整数C,D,由一个空格隔开,分别表示这一对朋友村庄沿河岸与PALMIA河最西边界的距离(C代表北岸的村庄,D代表南岸的村庄),不存在同岸又同位置的村庄。最后一组数据的下面仅有一行,是两个0,也被一空格隔开。【输出文件】ships.out 对输入文件的每一组数据,输出文件应在连续的行中表示出最大可能满足上述条件的航线的数目。【输入样例】30 4722 42 610 315 129 817 174 20 0【输出样例】4【问题分析】这道题目相对来说思考难度较高,从字面意义上看不出问题的本质来,有点无法下手的感觉。这里我给大家推荐两种思考这类问题的方法。法一:寻找规律法(我前面总结提到的第3个方法)寻找规律自然要推几组数据,首先当然有从样例入手;仔细观察上图:红色航线是合法的,那么他们满足什么规律呢? C1 C2 C3 C4北岸红线的端点: 4 9 15 17南岸红线的端点: 2 8 12 17 D1 D2 D3 D4不难看出无论线的斜率如何,都有这样的规律:C1C2C3C4 且 D1D2D3D4如果我们把输入数据排升序,问题变抽象为:在一个序列(D)里找到最长的序列满足DIDJDk且ijk这样的话便是典型的最长非降子序列问题了。法二:边界条件法(我前面总结提到的第4个方法)边界法其实就是把数据往小了缩,显然N=1是答案是1。N=2时呢?考虑这样一组数据:N=2C1 D1C2 D2当 C1D2 那么一定会相交,反之则不会相交。当C1 C2时,如果D1D2 那么一定会相交,反之则不会相交。N=3C1 D1C2 D2C3 D3其实不用在推导N=3了,有兴趣的可以推导去。看N=2时就能得出:对于任意两条航线如果满足CiCj 且DiDj 则两条航线不相交。这样的话要想在一个序列里让所有的航线都不相交那比然满足,C1C2C3Cans且D1D2D3Dans ,也就是将C排序后求出最长的满足这个条件的序列的长度就是解。这样分析后显然是一个最长非降子序列问题。复杂度:排序可以用O(nlogn)的算法,求最长非降子序列时间复杂度是O(n2).总复杂度为O(n2).【源代码】program ships;constfin=ships.in;fout=ships.out;maxn=5010;typeretype=record C,D:longint; end;varx,y,n,ans:longint;a:array0.maxn of retype;opt:array0.maxn of longint;procedure init;var i:longint;begin readln(n); for i:=1 to n do read(ai.c,ai.d);end;procedure quick(L,r:longint);var i,j,x:longint; y:retype;begin i:=L; j:=r; x:=a(i+j) div 2.c; repeat while ai.cx do dec(j); if ij; if jL then quick(L,j); if ir then quick(i,r);end;procedure main;var i,j:longint;begin fillchar(opt,sizeof(opt),0); quick(1,n); for i:=1 to n do for j:=0 to i-1 do if (aj.dopti) then opti:=optj+1; ans:=-maxlongint; for i:=1 to n do if ansopti then ans:=opti; writeln(ans);end;beginassign(input,fin);reset(input);assign(output,fout);rewrite(output);read(x,y);while (x+y0) do begin init; main; read(x,y); end;close(input);close(output);end. 1.2背包问题首先说说背包问题的基本模型:现有N个物品,每个物品的价值为V,重量为W。求用一个载重量为S的背包装这写物品,使得所装物品的总价值最高。背包问题用贪心和搜索解,当然效果不佳,不过在我的贪心和搜索总结中会说到。显然标准的解法是动态规化,我在解决这个问题时习惯设计一维状态,还可以设计二维的,二维状态在下面会讲,现在只讨论用一维状态实现背包问题。背包问题的分类:(1)小数背包:物品的重量是实数,如油,水等可以取1.67升(2)整数背包:0/1背包:每个物品只能选一次,或不选。不能只选一部分部分背包:所选物品可以是一部分。(3)多重背包:背包不只一个。小数背包:在贪心总结中会细讲。整数背包: 部分背包:同小数背包。0/1背包:这个问题是最经常出现的问题,应该熟练掌握。我们先看一下0/1背包的简化版: 现有N个物品,每个物品重量为W,这些物品能否使在载重量为S的背包装满(即重量和正好为S)?如过不能那能使物品重量和最重达到多少? 针对这一问题我们以物品的个数分阶段,设计一个状态opti表示载重量为i的背包可否装满,显然opti的基类型是boolean。决策是什么呢? 当要装第i个物品时,如果前i-1个物品可以使载重为 k的背包装满,那么载重为k+wi的背包就可以装满。于是对于一个optj来说,只要optj-wi是true(表示可装满)那optj就可以装满,但要注意:针对每一个物品枚举背包的载重量时如果这样正向的推导会使同一个物品用好几次,因为k+wi可装满那k+wi+wi就可装满,但实际上是装不满的因为物品只有一个。解决这个问题很简单,只要逆向推导就OK了。这样划分阶段,设计状态,满足无后效性和么?显然对与一个每一个阶段都是独立的,物品的顺序并不影响求解,因为装物品的次序不限。而对于optj只考虑optj-wi而不考虑后面的,所以满足无后效性。有了上面的分析不难写出状态转移方程:optj:=optj-w1 optj-wi=true时间复杂度:阶段数O(S)*状态数(O(N))*转移代价(O(1))=O(SN)下面看几个例题:例题5装箱问题(pack.pas/c/cpp)来源:NOIP2001(普及组) 第四题【问题描述】有一个箱子容量为V(正整数,0V20000),同时有n个物品(0n30,每个物品有一个体积(正整数)。要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。【输入文件】 第一 行一个正整数V表示箱子的容量,第二行一个正整数N表示物品个数,接下来N行列出这N个物品各自的体积。【输出文件】 单独一行,表示箱子最小的剩余空间。【输入样例】2468312797【输出样例】 0【问题分析】本题是经典的0/1背包问题,并且是0/1背包的简化版,把箱子看做背包,容量看做载重量,体积看做重量,剩余空间最小也就是尽量装满背包。于是这个问题便成了:有一个栽重量为V的背包,有N个物品,尽量多装物品,使背包尽量的重。设计一个状态opti表示重量i可否构成。状态转移方程:optj:=optj-w1 optj-wi=true最终的解就是v-x(x=n 且optx=true 且 optx+1.n=false)。【源代码1】program pack;constfin=pack.in;fout=pack.out;maxv=20010;maxn=100;varopt:array0.maxv of boolean;w:array0.maxn of longint;v,n,x:longint;procedure init;var i:longint;begin assign(input,fin); reset(input); assign(output,fout); rewrite(output); read(v); read(n); for i:=1 to n do read(wi);end;procedure main;var i,j:longint;begin fillchar(opt,sizeof(opt),false); opt0:=true; for i:=1 to n do for j:=v downto wi do if optj-wi then optj :=true; x:=v; while not optx do dec(x);end;procedure print;begin writeln(v-x); close(input); close(output);end;begininit;main;print;end. 例题6砝码称重来源:NOIP1996(提高组) 第四题【问题描述】 设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重=1000),用他们能称出的重量的种类数。【输入文件】 a1 a2 a3 a4 a5 a6 (表示1g砝码有a1个,2g砝码有a2个,20g砝码有a6个,中间有空格)。【输出文件】 Total=N (N表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况)。【输入样例】 1 1 0 0 0 0【输出样例】 TOTAL=3【问题分析】把问题稍做一个改动,已知a1+a2+a3+a4+a5+a6个砝码的重量wi, wi 1,2,3,5,10,20 其中砝码重量可以相等,求用这些砝码可称出的不同重量的个数。这样一改就是经典的0/1背包问题的简化版了,求解方法完全和上面说的一样,这里就不多说了,只是要注意这个题目不是求最大载重量,是统计所有的可称出的重量的个数。【源代码1】program P4;constmaxn=1010;w:array1.6 of longint=(1,2,3,5,10,20);varopt:array0.maxn of boolean;a:array1.6 of longint;procedure init;var i:longint;begin for i:=1 to 6 do read(ai);end;procedure main;var i,j,k:longint;begin fillchar(opt,sizeof(opt),false); opt0:=true; for i:=1 to 6 do for j:=1 to ai do for k:=maxn downto wi do if optk-wi then optk:=true;end;procedure print;var ans,i:longint;begin ans:=0; for i:=1 to maxn do if opti theninc(ans); writeln(ans);end;begininit;main;print;end. 例题7积木城堡 来源:vijos P1059【问题描述】 XC的儿子小XC最喜欢玩的游戏用积木垒漂亮的城堡。城堡是用一些立方体的积木垒成的,城堡的每一层是一块积木。小XC是一个比他爸爸XC还聪明的孩子,他发现垒城堡的时候,如果下面的积木比上面的积木大,那么城堡便不容易倒。所以他在垒城堡的时候总是遵循这样的规则。 小XC想把自己垒的城堡送给幼儿园里漂亮的女孩子们,这样可以增加他的好感度。为了公平起见,他决定把送给每个女孩子一样高的城堡,这样可以避免女孩子们为了获得更漂亮的城堡而引起争执。可是他发现自己在垒城堡的时候并没有预先考虑到这一点。所以他现在要改造城堡。由于他没有多余的积木了,他灵机一动,想出了一个巧妙的改造方案。他决定从每一个城堡中挪去一些积木,使得最终每座城堡都一样高。为了使他的城堡更雄伟,他觉得应该使最后的城堡都尽可能的高。任务: 请你帮助小XC编一个程序,根据他垒的所有城堡的信息,决定应该移去哪些积木才能获得最佳的效果。【输入文件】 第一行是一个整数N(N0 do begin inc(to
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 汉字“牛”的讲解课件
- 水银血压计使用课件
- 混凝土养护与加速养护方案
- 学生宿舍照明节能与智能控制方案
- 混凝土混合物的性能检测与控制方案
- 标准厂房安全出口与疏散方案
- 水电镀基础知识培训课件
- 胰岛素赵娜娜51课件
- 二零二五版服务业劳动保障监察及员工权益保障合同
- 二零二五年度公务车借用协议书模板
- 初中数学-综合与实践 哪一款“套餐”更合适教学课件设计
- 采油采气井控题库
- “三重一大”决策 标准化流程图 20131017
- Cpk 计算标准模板
- 精选浙江省普通高中生物学科教学指导意见(2023版)
- “魅力之光”核电知识竞赛试题答案(二)(110道)
- 外科学课件:食管癌
- 汽机专业设备运行日常点检
- GB/T 2820.12-2002往复式内燃机驱动的交流发电机组第12部分:对安全装置的应急供电
- 设备基础知识-动设备课件
- GB/T 12599-2002金属覆盖层锡电镀层技术规范和试验方法
评论
0/150
提交评论