描述
使用1角、2角、5角硬币组成 n 角钱。
设1角、2角、5角的硬币各用了a、b、c个,列出所有可能的a, b, c组合。 输出顺序为:先按c的值从小到大,若c相同则按b的值从小到大。
输入
一个整数n(1 <= n <= 100),代表需要组成的钱的角数。
输出
输出有若干行,每行的形式为: i a b c
第1列i代表当前行数(行数从001开始,固定3个字符宽度,宽度不足3的用0填充),后面3列a, b, c分别代表1角、2角、5角硬币的个数(每个数字固定12个字符宽度,宽度不足的在左边填充空格)。
样例输入
10 样例输出 001 10 0 0 002 8 1 0 003 6 2 0 004 4 3 0 005 2 4 0 006 0 5 0 007 5 0 1 008 3 1 1 009 1 2 1 010 0 0 2 源代码:
#include #include int t=1; int i,j,k; int n; scanf(\"%d\int A=n,B=n/2,C=n/5; for(i=0;i<=C;i++){ for(j=0;j<=B;j++){ for(k=0;k<=A;k++){ if(i*5+j*2+k*1==n){ printf(\"%03d%12d%12d%12d\\n++; } } } } getchar(); return 0; 2、比赛排名 描述 5名运动员参加100米赛跑,各自对比赛结果进行了预测: A说:E是第1名。 B说:我是第2名。 C说:A肯定垫底。 D说:C肯定拿不了第1名。 E说:D应该是第1名。 比赛结束后发现,只有获第1名和第2名的选手猜对了,E不是第2名和第3名,没有出现名次并列的情况。 请编程判断5位选手各是第几名。 输入 无 输出 输出要求:按ABCDE的顺序输出5行,其中第1行是A的名次,第2行是B的名次, 第3行是C的名次,第4行是D的名次,第5行是E的名次。 样例输入 样例输出 源代码: #include printf(\"5\\n\"); printf(\"2\\n\"); printf(\"1\\n\"); printf(\"3\\n\"); printf(\"4\\n\"); return 0; } 3、鸡兔同笼 描述 一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物。 输入 一行,一个正整数a (a < 32768)。 输出 一行,包含两个正整数,第一个是最少的动物数,第二个是最多的动物数,两个正整数用一个空格分开。 如果没有满足要求的答案,则输出两个0,中间用一个空格分开。 样例输入 20 样例输出 5 10 源代码: #include int n; scanf(\"%d\if(n % 4== 0) printf(\"%d %d\else if(n % 4!= 0&&n % 2== 0) printf(\"%d %d\ else printf(\"0 0\"); return 0; } 4、谁是你的潜在朋友 描述 “臭味相投”——这是我们描述朋友时喜欢用的词汇。两个人是朋友通常意味着他们存在着许多共同的兴趣。然而作为一个宅男,你发现自己与他人相互了解的机会并不太多。幸运的是,你意外得到了一份北大图书馆的图书借阅记录,于是你挑灯熬夜地编程,想从中发现潜在的朋友。 首先你对借阅记录进行了一番整理,把N个读者依次编号为1,2,…,N,把M本书依次编号为1,2,…,M。同时,按照“臭味相投”的原则,和你喜欢读同一本书的人,就是你的潜在朋友。你现在的任务是从这份借阅记录中计算出每个人有几个潜在朋友。 输入 第一行两个整数N,M,2 <= N ,M<= 200。接下来有N行,第i(i = 1,2,…,N)行每一行有一个数,表示读者i-1最喜欢的图书的编号P(1<=P<=M) 输出 包括N行,每行一个数,第i行的数表示读者i有几个潜在朋友。如果i和任何人都没有共同喜欢的书,则输出“BeiJu”(即悲剧,^ ^) 样例输入 4 5 2 3 2 1 样例输出 1 BeiJu 1 BeiJu 源代码: #include scanf(\"%d%d\ for(int i = 1; i <= n; i++ ){ scanf(\"%d\ b[ a[ i ] ]++; } for( int i = 1; i <= n; i++ ){ if( b[ a[ i ] ] == 1 ) printf(\"BeiJu\\n\"); else if( b[ a[ i ]] >= 2 ) printf(\"%d\\n\ } return 0; } 5、称体重 描述 、钱、、四个人中既有大人也有小孩,给他们称体重时发现,他们每个人的体重都不一样,且体重(单位:公斤)恰好是10的整数倍,且他们的体重都不高 于50公斤,已知、钱两人的体重之和恰好等于、两人的体重之和;、两人的体重之和大于、钱两人的体重之和,并且、俩人的体重之和还小于钱的体重。请编写一个程序,按照体重从小到大的顺序,打印出四人的姓氏的首字母和体重数。 输入 无 输出 打印出四人的姓氏的首字母(小写)和体重数(每人一行,首字母和体重数之间用空格隔开)。 样例输入 无 样例输出 z 10 q 20 s 30 l 40 (以上输出仅用于说明格式) #include int a[4],b[4]={1,2,3,4},c[4]={'z','q','s','l'}; int i,j,t; for(a[0]=1;a[0]<=5;a[0]++){ for(a[1]=1;a[1]<=5;a[1]++){ for(a[2]=1;a[2]<=5;a[2]++){ for(a[3]=1;a[3]<=5;a[3]++){ if((a[1]!=a[0]&&a[2]!=a[1]&&a[2]!=a[0]&&a[3]!=a[2]&&a[3]!=a[1]&&a[3]!=a[0]) &&(a[0]+a[1]==a[2]+a[3])&&(a[0]+a[3]>a[1]+a[2])&&(a[0]+a[2]for(i=0;i<4;i++){ a[i]=b[i]; } } for(i=0;i<4;i++){ b[i]=a[i]; } } } } for(i=0;i<4;i++){ for(j=i+1;j<4;j++){ if(b[i]>b[j]){ t=b[i]; b[i]=b[j]; b[j]=t; } } } for(j=0;j<4;j++){ } } for(i=0;i<4;i++){ } if(a[i]==b[j]){ } printf(\"%c %d\\n\ getchar(); return 0; 6、比饭量 描述 3个人比饭量,每人说了两句话: A说:B比我吃的多,C和我吃的一样多 B说:A比我吃的多,A也比C吃的多 C说:我比B吃得多,B比A吃的多。 事实上,饭量和正确断言的个数是反序的关系。 请编程按饭量的大小输出3个人的顺序。 输入 无输入 输出 按照饭量大小输出3人顺序,比如: ABC 样例输入 无 样例输出 无 #include for(B=1;B<=3;B++){ for(C=1;C<=3;C++){ a=((B>A)+(C==A)); b=((A>B)+(A>C)); c=((C>B)+(B>A)); if( ((A>B&&ab)) + ((A>C&&a if(b>a&&b>c){ } if(c>a&&c>b){ if(a>b) printf(\"CAB\"); if(a>c) printf(\"BAC\"); else printf(\"BCA\"); if(b>c) printf(\"ABC\"); else printf(\"ACB\"); } else printf(\"CBA\"); } } } } getchar(); return 0; } 7、求排列的逆序数 描述 在Internet上的搜索引擎经常需要对信息进行比较,比如可以通过某个人对一些事物的排名来估计他(或她)对各种不同信息的兴趣,从而实现个性化的服务。 对于不同的排名结果可以用逆序来评价它们之间的差异。考虑1,2,…,n的排列i1,i2,…,in,如果其中存在j,k,满足 j < k 且 ij > ik, 那么就称(ij,ik)是这个排列的一个逆序。 一个排列含有逆序的个数称为这个排列的逆序数。例如排列 263451 含有8个逆序 (2,1),(6,3),(6,4),(6,5),(6,1),(3,1),(4,1),(5,1),因此该排列的逆序数就是8。显然,由1,2,…,n 构成的所有n!个排列中,最小的逆序数是0,对应的排列就是1,2,…,n;最大的逆序数是n(n-1)/2,对应的排列就是n,(n-1),…,2,1。逆序数越大的排列与原始排列的差异度就越大。 现给定1,2,…,n的一个排列,求它的逆序数。 输入 第一行是一个整数n,表示该排列有n个数(n <= 100000)。 第二行是n个不同的正整数,之间以空格隔开,表示该排列。 输出 输出该排列的逆序数。 样例输入 6 2 6 3 4 5 1 样例输出 8 提示 1. 利用二分归并排序算法(分治); 2. 注意结果可能超过int的围,需要用long long存储。 #include const int MAX_NUM = 100000 + 5; long long seq[MAX_NUM]; int N; long long ans; void reSeq(long long* seq, int lef, int righ) {//用long long存储,避免结果超过int的围 if(lef >= righ) { return ; } int mid = lef + (righ - lef) / 2; reSeq(seq, lef, mid); reSeq(seq, mid + 1, righ); int totalSize = righ - lef + 1; long long tmp[totalSize]; int n = lef; int m = mid + 1; int i = 0; while(n <= mid || m <= righ) { if(m > righ || (n <= mid && seq[n] <= seq[m])) { tmp[i++] = seq[n++]; } else { tmp[i++] = seq[m++]; ans += mid - n + 1; } } i = lef; for(int j = 0; j < totalSize; j++) { seq[i++] = tmp[j]; } } void reSeqNum(long long* seq, int n) { reSeq(seq, 0, n - 1); } int main() { scanf(\"%d\ for(int i = 0; i < N; i++) { scanf(\"%ld\ } ans = 0; reSeqNum(seq, N); printf(\"%ld\\n\ return 0; } 8、Grey码 描述 Grey码是一个长度为2的序列,序列中无相同元素,且每个元素都是长度为n的二进制位 3 串,相邻元素恰好只有1位不同。例如长度为2的格雷码为 (000,001,011,010,110,111,101,100)。设计分治算法对任意的n值构造相应的Grey码。 n 输入 每个元素的长度值n。 输出 将所有相应的Grey码分行输出,即每一行输出一个二进制位串。 样例输入 3 样例输出 000 001 011 010 110 111 101 100 源代码: #include int i,p=1; for(i=1;i<=n;++i) p=p*base; return p; } void Grey(int a,int b,int **arr,int k){ if(b==1){ *((int*)arr+k*0+0)=0; //arr[0][0]=0; *((int*)arr+k*1+0)=1; //arr[1][0]=1; return ; }else{ for(int i=0;i*((int*)arr+k*i+b-1)=0; //arr[i][b-1]=0; *((int*)arr+k*(a-i-1)+b-1)=1; //arr[a-i-1][b-1]=1; } } Grey(a/2,b-1,(int **)arr,k); for(int i=a/2;ifor(int j=0;j } } int main(){ } int n; scanf(\"%d\int m=(int)power(2,n); int arr[m][n]; Grey(m,n,(int **)arr,n); for(int i=0;i printf(\"\\n\"); printf(\"%d\ 9、循环比赛 描述 设有N个选手的循环比赛。其中N=2^M(2的M次方),要求每名选手要与其他N-1名选手都赛一次,每名选手每天比赛一次,循环赛共进行N-1天,要求每天没有选手轮空。 输入 M 输出 表格形式的比赛安排表 样例输入 3 样例输出 1 2 3 4 5 6 7 8 2 1 4 3 6 5 8 7 3 4 1 2 7 8 5 6 4 3 2 1 8 7 6 5 5 6 7 8 1 2 3 4 6 5 8 7 2 1 4 3 7 8 5 6 3 4 1 2 8 7 6 5 4 3 2 1 提示 M的大小不会超过8 源代码: #include void arrange(int k,int **a,int n){ int t=1,temp=1; *((int*)a+k*0+0)=1; } //a[0][0]=1; while(t<=n){ } for(int i=0;i *((int*)a+k*(i+temp)+j+temp)=*((int*)a+k*i+j); //a[i+temp][j+temp]=a[i][j]; for(int j=0;j int main(){ int n; scanf(\"%d\int k=1; for(int i=0;i k=2*k; arrange(k,(int **)a,n); for(int i=0;i getchar(); return 0; for(int j=0;j printf(\"%d\ 10、棋盘覆盖问题 描述 在一个2×2个方格组成的棋盘中,若恰有一个方格与其他方格不同,称该方格为特殊方格, kk 且称该棋盘为特殊棋盘。显然,特殊方格在棋盘中出现的位置有4种情形,因而有4种不同的棋盘,如图1所示是k=2时16种棋盘中的一个。在棋盘覆盖问题中,要求用图2所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何两个L型骨牌不得重叠覆盖。 k k 输入 对每一个测试例有2行,第一行是k(1<=k<=10),第二行是特殊方格所在的位置坐标x,y(0<=x,y<1024)。 输出 边长为2的k次方的方阵,特殊方格的编号为0,所有L型骨牌从1开始编号,数据之间的间隔是空格。 样例输入 2 0 1 样例输出 2 0 3 3 2 2 1 3 4 1 1 5 4 4 5 5 提示 按分治策略进行算法设计。 #include int board[100][100]; void ChessBoard(int tr,int tc,int dr,int dc,int size){ int s,t1; if(size==1) return ; t1=++t; s=size/2; if(dr }else{ } board[tr+s-1][tc+s-1]=t1; ChessBoard(tr,tc,tr+s-1,tc+s-1,s); if(dr ChessBoard(tr,tc+s,dr,dc,s); }else{ } board[tr+s-1][tc+s]=t1; ChessBoard(tr,tc+s,tr+s-1,tc+s,s); if(dr>=tr+s&&dc }else{ } board[tr+s][tc+s-1]=t1; ChessBoard(tr+s,tc,tr+s,tc+s-1,s); if(dr>=tr+s&&dc>=tc+s){ ChessBoard(tr+s,tc+s,dr,dc,s); }else{ } board[tr+s][tc+s]=t1; ChessBoard(tr+s,tc+s,tr+s,tc+s,s); } int main(){ int n,size=1; scanf(\"%d\ for(int i=0;i size=size*2; int dr,dc; scanf(\"%d%d\ ChessBoard(0,0,dr,dc,size); for(int i=0;i printf(\"\\n\"); printf(\"%d \ } } getchar(); return 0; 11、输油管道问题 描述 某石油公司计划建造一条由东向西的主输油管道。该管道要穿过一个有n 口油井的油田。从每口油井都要有一条输油管道沿最短路经(或南或北)与主管道相连。如果给定n口油井的位置,即它们的x 坐标(东西向)和y 坐标(南北向),应如何确定主管道的最优位置,即使 各油井到主管道之间的输油管道长度总和最小的位置?证明可在线性时间确定主管道的最优位置。要求给定n口油井的位置,计算各油井到主管道之间的输油管道最小长度总和。 输入 由文件提供输入数据,文件第一行是油井数n,1<=n<=10000。接下来n行是油井的位置,每行两个整数x和y,-10000<=x,y<=10000。 输出 将结果输出到文件中,文件第一行中的数是油井到主管道之间的输油管道最小长度总和。 样例输入 5 1 2 2 2 1 3 3 -2 3 3 样例输出 6 提示 按分治策略进行算法设计。 源代码: #include int x,y; } num[200000]; bool cmp(node a,node b) { return a.y int t; scanf(\"%d\ int i,j; for(i=0;i sort(num,num+t,cmp); if(t%2==1) { ans=0; int zong=num[t/2].y; for(i=0;i else { int zong=num[t/2].y+num[t/2-1].y; zong/=2; ans=0; for(i=0;i printf(\"%d\\n\ return 0; } 12、0/1背包问题 描述 给定n种物品和一个背包,物品i(1≤i≤n)的重量是wi,其价值为vi,背包的容量为C,对每种物品只有两种选择:装入背包或者不装入背包。如何选择装入背包的物品,使得装入背包中物品的总价值最大? 输入 输入包含一组或多组测试例。每组测试例的第一行是物品的数量n和背包的容量C,之后的n行是每个物品的重量及其价值。 输出 输出第一行是装入背包中物品的总价值,后面n行是各个物品装入背包的情况。 样例输入 5 10 2 6 2 3 6 5 5 4 4 6 样例输出 15 1 1 0 0 1 源代码: #include int i, j, k; k=c; for(i=n; i>=1; i--){ if(dp[i][k]!=dp[i-1][k]){ ans[i]=1; k=k-w[i]; } } } else{ } return; int main(){ int i, j, k; scanf(\"%d%d\for(i=1; i<=n; i++){ } for(i=1; i<=n; i++){ } printf(\"%d\\n\print(); for(i=1; i<=n; i++) { printf(\"%d\\n\for(j=1; j<=c; j++){ } dp[i][j]=dp[i-1][j]; if(j>=w[i]){ } dp[i][j]=max(dp[i-1][j-w[i]]+v[i], dp[i][j]); scanf(\"%d%d\ } } return 0; 13、最少硬币问题 描述 设有n种不同面值的硬币,各硬币的面值存于数组T[1:n]中。现要用这些面值的硬币来找钱。可以使用的各种面值的硬币个数存于数组Coins[1:n]中。对任意钱数0≤m≤20001,设计一个用最少硬币找钱m的方法。 对于给定的1≤n≤10,硬币面值数组T和可以使用的各种面值的硬币个数数组Coins,以及钱数m,0≤m≤20001,计算找钱m的最少硬币数。 输入 由文件提供输入数据,文件的第一行中只有1个整数给出n的值,第2行起每行2 个数,分别是T[j]和Coins[j]。最后1行是要找的钱数m。 输出 将计算出的最少硬币数输出到文件中。问题无解时输出-1。 样例输入 3 1 3 2 3 5 3 18 样例输出 5 提示 运用动态规划法进行算法设计并编程实现。 源代码: #include int main(){ int i, j, k; int t, x,t=1; scanf(\"%d\for(i=1; i<=n; i++){ } scanf(\"%d%d\for(j=1; j<=x; j++){ } w[cnt]=t; v[cnt]=1; cnt++; for(int i=0; i<110; i++){ } for(int j=0; j<20010; j++){ } dp[i][j]=2000000000; } scanf(\"%d\init(); for(i=0; i printf(\"%d\return 0; for(j=1; j<=m; j++){ } dp[i][j]=dp[i-1][j]; if(j>=w[i]&&dp[i-1][j-w[i]]!=2000000000){ } dp[i][j]=min(dp[i][j], dp[i-1][j-w[i]]+1); //cnt++; dp[i][0]=0; 14、矩阵连乘 描述 给定n个矩阵{A1,A2,...,An},考察这n个矩阵的连乘积A1A2...An。由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序,这种计算次序可以用加括号的方式来确定。 矩阵连乘积的计算次序与其计算量有密切关系。例如,考察计算3个矩阵{A1,A2,A3}连乘积的例子。设这3个矩阵的维数分别为10*100,100*5,和5*50。若按(A1A2)A3计算,3个矩阵连乘积需要的数乘次数为10*100*5+10*5*50 = 7500。若按A1(A2A3)计算,则总共需要100*5*50+10*100*50 = 75000次数乘。 现在你的任务是对于一个确定的矩阵连乘方案,计算其需要的数乘次数。 输入 输入数据由多组数据组成。每组数据格式如下: 第一行是一个整数n (1≤n≤26),表示矩阵的个数。 接下来n行,每行有一个大写字母,表示矩阵的名字,后面有两个整数a,b,分别表示该矩阵的行数和列数,其中1第n+1行是一个矩阵连乘的表达式,由括号与大写字母组成,没有乘号与多余的空格。如果表达式中没有括号则按照从左到右的顺序计算,输入的括号保证能够配对。 输出 对于每组数据,输出仅一行包含一个整数,即将该矩阵连乘方案需要的数乘次数。如果运算过程中出现不满足矩阵乘法法则的情况(即左矩阵列数与右矩阵的行数不同),则输出“error”。 样例输入 3 A 10 100 B 100 5 C 5 50 A(BC) 样例输出 75000 源代码: # include # include node s[200]; int flage; stack string change(string t){ int length=t.length(); string des=\"\"; for(int i=0; i else if(t[i]=='('){ if(t[i+1]==')'){ } else{ } des=des+t[i]+'*'; des=des+t[i]; int x,y; } } } des=des+t[i]; else{ } if(t[i+1]==')'){ } else{ } des=des+t[i]+'*'; des=des+t[i]; des=des+t[length-1]+'='; return des; node calc(node a, node b){ } char compare(char i, char j){ if(i=='='){ if(a.y!=b.x){ } node t; ans=ans+a.x*a.y*b.y; t.x=a.x;t.y=b.y; return t; flage=1; } } if(j!='='){ } else{ } return '='; return '<'; if(i=='('){ } if(i=='*'){ } if(j=='('){ } else{ } return '>'; return '<'; if(j==')'){ } else{ } return '<'; return '='; int main(){ int i, j, k; string e; while(cin>>n){ for(i=1; i<=n; i++){ } cin>>e; flage=0; ans=0; exp=change(e); while(!ope.empty()){ } while(!v.empty()){ } ope.push('='); int l=exp.length(); for(k=0; k<=l-1; ){ if(isalpha(exp[k])){ } v.push(s[exp[k]]); k++; v.pop(); ope.pop(); cin>>str>>x>>y; s[str[0]].x=x; s[str[0]].y=y; } } else{ } if(compare(ope.top(), exp[k])=='='){ } else if(compare(ope.top(), exp[k])=='<'){ } else{ } node a=v.top(); v.pop(); node b=v.top(); v.pop(); v.push(calc(b, a)); ope.pop(); ope.push(exp[k]); k++; ope.pop(); k++; if(!flage) cout< } 15、多边形游戏 描述 一个多边形,开始有n个顶点。每个顶点被赋予一个正整数值,每条边被赋予一个运算符“+”或“*”。所有边依次用整数从1到n编号。 现在来玩一个游戏,该游戏共有n步: 第1步,选择一条边,将其删除 随后n-1步,每一步都按以下方式操作:(1)选择一条边E以及由E连接着的2个顶点v1和v2; (2)用一个新的顶点取代边E以及由E连接着的2个顶点v1和v2,将顶点v1和v2的整数值通过边E上的运算得到的结果值赋给新顶点。 最后,所有边都被删除,只剩一个顶点,游戏结束。游戏得分就是所剩顶点上的整数值。那么这个整数值最大为多少? 输入 第一行为多边形的顶点数n(n ≤ 20),其后有n行,每行为一个整数和一个字符,整数为顶点上的正整数值,字符为该顶点到下一个顶点间连边上的运算符“+”或“*”(最后一个字符为最后一个顶点到第一个顶点间连边上的运算符)。 输出 输出仅一个整数,即游戏所计算出的最大值。 样例输入 4 4 * 5 + 5 + 3 + 样例输出 70 提示 小规模问题可不必用动态规划方法编程求解,仅用递归就可以求解。 计算中不必考虑计算结果超出整数表达围的问题,给出的数据能保证计算结果的有效性。 在给的例子中,计算过程为(3+4)*(5+5)=70。 源代码: #include char op[110][110]; ll dp[110][110], dpmin[110][110]; ll a[110]; ll calc(ll a, ll b, char ch){ if(ch=='*'){ } else if(ch=='+'){ } else{ } return 0; return a+b; return a*b; } int main(){ int i, j, k, t; cin>>n; for(i=1; i<=n; i++){ } cin>>t; a[i]=t; cin>>s; op[i][i+1]=s[0]; for(i=n+1; i<=2*n; i++){ } // for(i=1; i<=2*n; i++){ // printf(\"%d \// } // printf(\"\\n\"); for(i=n+1; i<2*n; i++){ } op[i][i+1]=op[i-n][i+1-n]; a[i]=a[i-n]; // for(i=1; i<2*n; i++){ // printf(\"%c \// } // printf(\"\\n\"); for(i=1; i<=2*n; i++){//初始化为最小值 } for(i=1; i<=2*n; i++){ } for(i=1; i<2*n; i++){ } for(i=3; i<=n; i++){ for(j=1; j+i-1<=2*n; j++){ dp[i][i+1]=calc(a[i], a[i+1], op[i][i+1]); dpmin[i][i+1]=calc(a[i], a[i+1], op[i][i+1]); dp[i][i]=a[i]; dpmin[i][i]=a[i]; for(j=i; j<=2*n; j++){ } dp[i][j]=-inf; dpmin[i][j]=inf; for(k=j; kdp[j][i+j-1]=max(dp[j][i+j-1], calc(dpmin[j][k], dp[j][i+j-1]=max(dp[j][i+j-1], calc(dpmin[j][k], dp[k+1][i+j-1], dp[j][i+j-1]=max(dp[j][i+j-1], calc(dp[j][k], dpmin[k+1][i+j-1], dp[j][i+j-1]=max(dp[j][i+j-1], calc(dp[j][k], dp[k+1][i+j-1], dpmin[k+1][i+j-1], op[k][k+1])); } for(k=j; kdpmin[j][i+j-1]=min(dpmin[j][i+j-1], calc(dp[j][k], dp[k+1][i+j-1], op[k][k+1])); dpmin[j][i+j-1]=min(dpmin[j][i+j-1], calc(dp[j][k], dpmin[k+1][i+j-1], op[k][k+1])); dpmin[j][i+j-1]=min(dpmin[j][i+j-1], calc(dpmin[j][k], dp[k+1][i+j-1], op[k][k+1])); dpmin[j][i+j-1]=min(dpmin[j][i+j-1], calc(dpmin[j][k], dpmin[k+1][i+j-1], op[k][k+1])); } } ll ans=-inf-10000000; for(i=1; i<=n; i++){ } cout< ans=dp[i][i+n-1]; } } 16、最优合并问题 描述 给定k个排好序的序列s1, s2, s3,..., sk, 用2路合并算法将这k个序列合并成一个序列。假设所采用的2路合并算法合并2个长度分别为m和n的序列需要m+n-1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。 为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。 输入 由文件给出输入数据。第一行有1个正整数k,表示有k个待合并序列。接下来的1行中,有k个正整数,表示k个待合并序列的长度。 输出 将计算出的最多比较次数和最少比较次数输出到文件。 样例输入 4 5 12 11 2 样例输出 78 52 提示 使用贪心法进行算法设计并编程实现。 17、最优服务次序问题 描述 设有n个顾客同时等待一项服务。顾客i需要的服务时间为ti,1≤i≤n。应如何安排n个顾客的服务次序才能使平均等待时间达到最小?平均等待时间是n个顾客等待服务时间的总和除以n。 对于给定的n个顾客需要的服务时间,计算最优服务次序。 输入 由文件给出输入数据。第一行是正整数n,表示有n个顾客。接下来的1行中,有n个正整数,表示n个顾客需要的服务时间。 输出 将计算出的最小平均等待时间输出到文件。 样例输入 10 56 12 1 99 1000 234 33 55 99 812 样例输出 532.00 提示 使用贪心法设计算法并编程实现。 源代码: #include int n; int a[100]; scanf(\"%d\int sum=0; int temp=0; for(int i=0;i } { } printf(\"%.2lf\return 0; temp+=a[i]; sum+=temp; 因篇幅问题不能全部显示,请点此查看更多更全内容ChessBoard(tr,tc,dr,dc,s); =tc+s){