ImageVerifierCode 换一换
格式:DOCX , 页数:118 ,大小:263.03KB ,
资源ID:10853194      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10853194.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(acm备考资料整理by liangge.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

acm备考资料整理by liangge.docx

1、acm备考资料整理by liangge背包问题P01: 01背包问题题目有N件物品和一个容量为V的背包。第i件物品的费用是ci,价值是wi。求解将哪些物品装入背包可使价值总和最大。基本思路这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。用子问题定义状态:即fiv表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:fiv=maxfi-1v,fi-1v-ci+wi先考虑上面讲的基本思路如何实现,肯定是有一个主循环i=1.N,每次算出来二维数组fi0.V的所有值。那么,如果只用一个数组 f0.V,能不能保证第i次循环结束后fv中表示的就是我们定义的状态f

2、iv呢?fiv是由fi-1v和fi-1 v-ci两个子问题递推而来,能否保证在推fiv时(也即在第i次主循环中推fv时)能够得到fi-1v和fi-1 v-ci的值呢?事实上,这要求在每次主循环中我们以v=V.0的顺序推fv,这样才能保证推fv时fv-ci保存的是状态 fi-1v-ci的值。伪代码如下:for i=1.Nfor v=V.0fv=maxfv,fv-ci+wi;其中的fv=maxfv,fv-ci一句恰就相当于我们的转移方程fiv=maxfi-1v,fi-1v-ci,因为现在的fv-ci就相当于原来的fi-1v-ci。如果将v的循环顺序从上面的逆序改成顺序的话,那么则成了fiv由fiv

3、-ci推知,与本题意不符,但它却是另一个重要的背包问题P02最简捷的解决方案,故学习只用一维数组解01背包问题是十分必要的。事实上,使用一维数组解01背包的程序在后面会被多次用到,所以这里抽象出一个处理一件01背包中的物品过程,以后的代码中直接调用不加说明。过程ZeroOnePack,表示处理一件01背包中的物品,两个参数cost、weight分别表明这件物品的费用和价值。procedure ZeroOnePack(cost,weight)for v=V.costfv=maxfv,fv-cost+weight初始化的细节问题我们看到的求最优解的背包问题题目中,事实上有两种不太相同的问法。有的题

4、目要求“恰好装满背包”时的最优解,有的题目则并没有要求必须把背包装满。一种区别这两种问法的实现方法是在初始化的时候有所不同。如果是第一种问法,要求恰好装满背包,那么在初始化时除了f0为0其它f1.V均设为-,这样就可以保证最终得到的fN是一种恰好装满背包的最优解。如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将f0.V全部设为0。为什么呢?可以这样理解:初始化的f数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为0的背包可 能被价值为0的nothing“恰好装满”,其它容量的背包均没有合法的解,属于未定义的状态,它们的值就都应该是-

5、了。如果背包并非必须被装满,那么 任何容量的背包都有一个合法解“什么都不装”,这个解的价值为0,所以初始时状态的值也就全部为0了。这个小技巧完全可以推广到其它类型的背包问题,后面也就不再对进行状态转移之前的初始化进行讲解。一个常数优化前面的伪代码中有 for v=V.1,可以将这个循环的下限进行改进。由于只需要最后fv的值,倒推前一个物品,其实只要知道fv-wn即可。以此类推,对以第j个背包,其实只需要知道到fv-sumwj.n即可,即代码中的for i=1.Nfor v=V.0可以改成for i=1.nbound=maxV-sumwi.n,cifor v=V.bound这对于V比较大时是有用

6、的。输入格式输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1=n=100, 1=m=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1=p=20,1=h=200,1=c=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。输出格式对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。输入样例18 22 100 44 100 2输出样例400#include#includeusing namespace std;#define N 1005

7、#define Max(a,b) (a)(b)?(a):(b)#define Min(a,b) (a)t; while(t-) cinmn; for(i=1;ivolivalinni; memset(dp,0,sizeof(dp); for(i=1;i=0;j-) max=-1; for(k=0;k=nni&k*voli=j;k+) max=Max(max,dpi-1j-k*voli+k*vali); dpij=max; coutdpnmendl; return 0;下面为 0-1背包问题,上面为多重背包#include using namespace std;#define MAXSIZE

8、1000int fMAXSIZE + 1, cMAXSIZE + 1, wMAXSIZE + 1;int main()int N, V;cin V N;int i = 1;for (; i ci wi;for (i = 1; i = ci; -v) /ci可优化为bound, bound = max V - sum ci,.n, cifv = (fv fv - ci + wi ? fv : fv - ci + wi);/当i=N时,可以跳出循环单独计算FVcout fV n;return 0;背包问题,贪心法#include #include #include using namespace

9、std;int i,j,n;float W,x1000,sum;struct rm float w; float v;room1000;bool cmp(rm a,rm b) return a.v/a.wb.v/b.w;int main() cinWn; while(n!=-1 & W!=-1) for(i=0;iroomi.vroomi.w; sort(room,room+n,cmp); memset(x,0,1000); i=0; while(roomi.wW) xi=roomi.v; W=W-roomi.w; i+; xi=roomi.v/roomi.w*W; j=0; sum=0.0;

10、 while(j=i) sum+=xj; j+; coutsetiosflags(ios:fixed)setprecision(3)sumWn; return 0;输入样例5 37 24 35 2-1 -1(结束)输出样例13.333 对v/w从大到小排列,再依次选择八皇后问题#include#include #include using namespace std;struct node1bool b88; struct node2int x,y; node1 visited9;node2 zb8;int num;void print()printf(case%d: ,+num);for(i

11、nt i=0;i=7;i+)printf(%d,%dt,zbi.x,zbi.y);coutn;int x1,y1,x4,y4;void vis(int x,int y,int step) x1=x;y1=y;x4=x;y4=y;visitedstep=visitedstep-1;for(int i=0;i8;i+)visitedstep.bxi=0;visitedstep.biy=0;while(x18&y18)visitedstep.bx1y1=0;x1+;y1+;while(x4=0)visitedstep.bx4y4=0;x4+;y4-;void DFS(int step)if(step

12、=9) print();elsefor(int j=0;j8;j+)if(visitedstep-1.bstep-1j)zbstep-1.x=step-1;zbstep-1.y=j;vis(step-1,j,step);DFS(step+1);int main()num=0;memset(visited,1,sizeof(visited);DFS(1);/couthello worldendl;system(pause);站位问题:#include #include using namespace std; int counter=0; void display(int place) for(

13、int i=1;i=6;i+) coutplaceit; if(i%3=0) coutn; coutendl; bool judge(int mark,int place) switch(mark) case 1: return true; case 2: return place2!=5&place2!=6; case 3: return place3!=2&place3!=3; case 4: return place4!=1&place4!=2&place4!=3&place4!=6; case 5: return place5!=1&place5!=5&place5!=6; case

14、6: return place6!=1&place6!=6; bool others(int place) int m=1,n=1; for(int i=0;i=6;i+) if(placei=3) m=i-1; if(placei=4) n=i-1; return m/3!=n/3; void backtrace(int mark,int place,int people) for(int i=1;i=6;i+) if(peoplei!=0) placemark=peoplei; if(judge(mark,place) if(mark=6&others(place) counter+; d

15、isplay(place); else peoplei=0; backtrace(mark+1,place,people); peoplei=i; int main(int argc, char *argv) int *place=new int7; int *people=new int7; for(int i=1;i=6;i+) peoplei=i; backtrace(1,place,people); coutThe total methods is counterendl; system(PAUSE); return EXIT_SUCCESS; 把一个数分解为若干数的和#include

16、 #include #define MAXSIZE 50static int buffMAXSIZE;int Sum(int buff,int i)int sum=0;for(int m=0;m =i;m+)sum+=buffm;return sum;void printFactor(int buff,int i,const int number)int count=0,m;for(m=0;m 0;j-)bufftop=j;if(number=Sum(buff,top)printFactor(buff,top,number);else if(number =number)continue;di

17、vide(j,top+1,number);return;void main()int i,top=0;int number;printf( input a souce number: );scanf(%d,&number);i=number;divide(i,top,number);普里姆prim最小生成数#include #include #define N 100int pN, keyN, tbNN; /keyj表示到达j点的路径void prim(int v, int n) int i, j; int min; for (i = 1; i = n; i+) /从第一个顶点开始找 pi =

18、 v; keyi = tbvi; /初始化到达i点的各个值 keyv = 0; for (i = 2; i = n; i+) min = INT_MAX; for (j = 1; j 0 & keyj 0保证访问不会构成环 min = keyj; printf(%d%d , pv, v); keyv = 0; /访问过的点被置为0 for (j = 1; j = n; j+) if (tbvj keyj) /保证到达j点的值最小 pj = v, keyj = tbvj; int main() int n, m; int i, j; int u, v, w; while (scanf(%d%d,

19、 &n, &m) /输入顶点数,边数和某点到某点的权值 for(i = 1; i = n; i+) for (j = 1; j = n; j+) tbij = INT_MAX; while (m-) scanf(%d%d%d, &u, &v, &w); tbuv = tbvu = w; prim(1, n); printf(n); return 0;Kruskal算法 N城市遍历问题(依次选取最小边组成生成数)#include #include #include #define max 20 #define MAX_LNT 10 typedef struct node /*构造一个结构体,两个

20、城市可以看成起点和终点,之间的道路可以看成一个边*/ int str; /*起点*/ int end; /*终点*/ int dis;/*距离*/ node; node pmax,temp; /*p记录城市信息*/ int pre100,rank100;/*用于判断是否构成回路*/ int n=0,arcsMAX_LNTMAX_LNT;/*n表示城市个数,arcs记录城市间权值*/ int menu( ) /*菜单函数*/ int m; printf(.2010年7月29日.nn); printf( 求最小生成树n); printf( _nn); printf( 1 输入城市之间的信息n);

21、printf( 2 判断是否能构成一个最小生成树n); printf( 3 遍历所有城市生成最小生成树n); printf( 4 退出n); printf( _nn); printf( 请输入所选功能1-4n); system(color E);/*改变界面颜色的,对程序没什么影响*/ scanf(%d,&m); return m; /*下面三个函数作用是检验当一条边添加进去,是否会产生回路*/ void set(int x)/*初始化*/ 11 prex = x; rankx = 0; int find(int x)/*找到这个点的祖先*/ if(x != prex) prex = find

22、(prex); return prex; void Union(int x,int y)/*将这两个添加到一个集合里去*/ x = find(x); y = find(y); if(rankx = ranky) prey = x; rankx +; else prey = x; void Kruskal( ) int ans = 0,i,j,k = 0; /*ans用来记录生成最小树的权总值*/ int index; int count = 0; /*记录打印边的条数*/ for(i = 1;i = n;i +) /*初始化数组prex,rankx*/ set(i); for(i = 1;i

23、= n;i +) for(j = i + 1;j = n;j +) p+k.str = i; pk.end = j; pk.dis = arcsij; /*先把所有城市之间的路段看成一个边*/ for(i=1;i=k;i+) /*把所有的边按从小到大进行排序*/ index=i; for(j=i+1;j=k;j+) if(pj.dis pindex.dis) index=j; 12 temp=pindex; pindex=pi; pi=temp; for(i = 1;i = k;i +) if(find(pi.str) != find(pi.end)/*如果这两点连接在一起不构成一个回路,则执行下面操作*/ printf(t第%d条路段为:%d-%d,权值为%dn,+ count,pi.str,pi.end,pi.dis);/*将这条边的起点、终点打印出来*/ ans += pi.dis; /*说明这条路段要用*/ Union(pi.str,pi.end); printf(t遍历所有城市得到最小生成树的代价为: %dnn,ans); void create( ) /*输入城市信息*/ int i,j; printf(请输入城市的个数:n

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1