33,311
社区成员
发帖
与我相关
我的任务
分享
//给定一个正整数序列a(1),a(2),...,a(n),(1<=n<=20)
//不改变序列中每个元素在序列中的位置,把它们相加,并用括号记每次加法所得的和,称为中间和。
// 例如:
// 给出序列是4,1,2,3。
// 第一种添括号方法:
//((4+1)+(2+3))=((5)+(5))=(10)
// 有三个中间和是5,5,10,它们之和为:5+5+10=20
// 第二种添括号方法
// (4+((1+2)+3))=(4+((3)+3))=(4+(6))=(10)
// 中间和是3,6,10,它们之和为19。
//描述 Description
// 现在要添上n-1对括号,加法运算依括号顺序进行,得到n-1个中间和,求出使中间和之和最小的添括号方法。
//输入格式 Input Format
// 共两行。
//第一行,为整数n。(1<=n<=20)
//第二行,为a(1),a(2),...,a(n)这n个正整数,每个数字不超过100。
//输出格式 Output Format
// 输出3行。
//第一行,为添加括号的方法。
//第二行,为最终的中间和之和。
//第三行,为n-1个中间和,按照从里到外,从左到右的顺序输出。
//
//时间限制 Time Limitation
// 各个测试点1s
//注释 Hint
// 在相同的情况下,括号尽可能的向左加
//
//一道典型区间dp题目,方程为f[i][j]=min(f[i][k]+f[k+1][j]+a[i][j]) (i<=k<j).
//f[i][j]为区间(i,j)的最小中间和之和,a[i][j]为区间(i,j)元素之和。
//用g[i][j]记录合并f[i][j]时的k值,最后递归输出,注意顺序即可。
//原题打错了,最后一句应该为“括号尽可能的向左加”,我已改正。
//类似的区间dp题目还有能量项链,合并傻子,合并沙子等,
//做这类题目要注意dp的变量循环顺序,一般在最外层枚举区间长度,最内层枚举断点,
//当然f[i][j]的意义也可以改变,只要注意方程的正确性即可。还有边界条件也是容易错的地方,需要注意。这类题目多加练习就没什么问题了。
#include <stdio.h>
#include <limits.h>
int a[21][21];
int f[21][21];
int g[21][21];
int i,j,k,n,t,l,kk;
void sout(int l,int r) {
if (l==r) {printf("%d",a[l][l]);return;}
printf("(");
sout(l,g[l][r]);
printf("+");
sout(g[l][r]+1,r);
printf(")");
}
void wout(int l,int r) {
if (l==r) return;
wout(l,g[l][r]);
wout(g[l][r]+1,r);
printf("%d ",f[l][r]-f[l][g[l][r]]-f[g[l][r]+1][r]);
}
int main() {
scanf("%d",&n);
for (i=1;i<=n;i++) scanf("%d",&a[i][i]);
for (i=1;i<=n-1;i++) {
for (j=i+1;j<=n;j++) {
a[i][j]=a[i][j-1]+a[j][j];
}
}
for (l=1;l<=n-1;l++) {
for (i=1;i<=n-l;i++) {
j=i+l;
t=INT_MAX;
for (k=i;k<=j-1;k++) {
if (f[i][k]+f[k+1][j]+a[i][j]<=t) {
t=f[i][k]+f[k+1][j]+a[i][j];
kk=k;
}
}
f[i][j]=t;
g[i][j]=kk;
}
}
sout(1,n);
printf("\n");
printf("%d\n",f[1][n]);
wout(1,n);
return 0;
}
//输入:
//4
//4 1 2 3
//输出:
//(4+((1+2)+3))
//19
//3 6 10
//http://bbs.csdn.net/topics/390893174
//多边形游戏
//描述
// 一个多边形,开始有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 <stdio.h>
int d[20],e[20],o[20];
char r[20];
char b[2];
char c;
int i,n,s;
int maxv;
int next_pl(int * f, int * l) {
int t;
int *ff,*ll,*i,*p,*j;
i = l;
if (f == l || f == --i) return (0);
while (1) {
p = i;
if (*--i < *p) {
j = l;
while (1) {
j--;
if (*i<*j) break;//
}
t=*i;*i=*j;*j=t;
ff=p;
ll=l;
for (; ff < ll; ++ff) {
ll--;
t=*ff;*ff=*ll;*ll=t;
}
return (1);
}
if (i == f) {
ff=f;
ll=l;
for (; ff < ll; ++ff) {
ll--;
t=*ff;*ff=*ll;*ll=t;
}
return (0);
}
}
}
void merge(int f) {//合并计算顶点f和f+1,并将结果覆盖到f和f+1
int t;
t=(f+1)%n;
switch (r[f]) {
case '+':
printf("e[%d]%ce[%d]=%d%c%d",f,r[f],t,e[f],r[f],e[t]);
e[f]=e[f]+e[t];
e[t]=e[f];
printf("=%d\n",e[f]);
break;
case '*':
printf("e[%d]%ce[%d]=%d%c%d",f,r[f],t,e[f],r[f],e[t]);
e[f]=e[f]*e[t];
e[t]=e[f];
printf("=%d\n",e[f]);
break;
}
}
void play(int s) {//从第s(0..n-1)个顶点开始,递归计算其后n-1条边消除的所有方案
int j,v;
for (j=0;j<n-1;j++) o[j]=j;
do {
for (j=0;j<n;j++) e[j]=d[j];
printf("o[]=");
for (j=0;j<n-1;j++) printf("%d",o[j]);
printf("\n");
for (j=0;j<n-1;j++) merge((s+o[j])%n);
v=e[(s+o[n-2])%n];
printf("v=%d\n",v);
if (maxv<v) maxv=v;
} while (next_pl(&o[0],&o[0]+n-1));
}
int main() {
scanf("%d",&n);
for (i=0;i<n;i++) {
scanf("%d%1s",&d[i],b);
r[i]=b[0];
}
maxv=0;
for (s=0;s<n;s++) {
c=r[s];
r[s]=' ';
play((s+1)%n);
r[s]=c;
}
printf("maxv=%d\n",maxv);
return 0;
}
//4
//4 *
//5 +
//5 +
//3 +
//o[]=012
//e[1]+e[2]=5+5=10
//e[2]+e[3]=10+3=13
//e[3]+e[0]=13+4=17
//v=17
//o[]=021
//e[1]+e[2]=5+5=10
//e[3]+e[0]=3+4=7
//e[2]+e[3]=10+7=17
//v=17
//o[]=102
//e[2]+e[3]=5+3=8
//e[1]+e[2]=5+8=13
//e[3]+e[0]=8+4=12
//v=12
//o[]=120
//e[2]+e[3]=5+3=8
//e[3]+e[0]=8+4=12
//e[1]+e[2]=5+8=13
//v=13
//o[]=201
//e[3]+e[0]=3+4=7
//e[1]+e[2]=5+5=10
//e[2]+e[3]=10+7=17
//v=17
//o[]=210
//e[3]+e[0]=3+4=7
//e[2]+e[3]=5+7=12
//e[1]+e[2]=5+12=17
//v=17
//o[]=012
//e[2]+e[3]=5+3=8
//e[3]+e[0]=8+4=12
//e[0]*e[1]=12*5=60
//v=60
//o[]=021
//e[2]+e[3]=5+3=8
//e[0]*e[1]=4*5=20
//e[3]+e[0]=8+20=28
//v=28
//o[]=102
//e[3]+e[0]=3+4=7
//e[2]+e[3]=5+7=12
//e[0]*e[1]=7*5=35
//v=35
//o[]=120
//e[3]+e[0]=3+4=7
//e[0]*e[1]=7*5=35
//e[2]+e[3]=5+7=12
//v=12
//o[]=201
//e[0]*e[1]=4*5=20
//e[2]+e[3]=5+3=8
//e[3]+e[0]=8+20=28
//v=28
//o[]=210
//e[0]*e[1]=4*5=20
//e[3]+e[0]=3+20=23
//e[2]+e[3]=5+23=28
//v=28
//o[]=012
//e[3]+e[0]=3+4=7
//e[0]*e[1]=7*5=35
//e[1]+e[2]=35+5=40
//v=40
//o[]=021
//e[3]+e[0]=3+4=7
//e[1]+e[2]=5+5=10
//e[0]*e[1]=7*10=70
//v=70
//o[]=102
//e[0]*e[1]=4*5=20
//e[3]+e[0]=3+20=23
//e[1]+e[2]=20+5=25
//v=25
//o[]=120
//e[0]*e[1]=4*5=20
//e[1]+e[2]=20+5=25
//e[3]+e[0]=3+20=23
//v=23
//o[]=201
//e[1]+e[2]=5+5=10
//e[3]+e[0]=3+4=7
//e[0]*e[1]=7*10=70
//v=70
//o[]=210
//e[1]+e[2]=5+5=10
//e[0]*e[1]=4*10=40
//e[3]+e[0]=3+40=43
//v=43
//o[]=012
//e[0]*e[1]=4*5=20
//e[1]+e[2]=20+5=25
//e[2]+e[3]=25+3=28
//v=28
//o[]=021
//e[0]*e[1]=4*5=20
//e[2]+e[3]=5+3=8
//e[1]+e[2]=20+8=28
//v=28
//o[]=102
//e[1]+e[2]=5+5=10
//e[0]*e[1]=4*10=40
//e[2]+e[3]=10+3=13
//v=13
//o[]=120
//e[1]+e[2]=5+5=10
//e[2]+e[3]=10+3=13
//e[0]*e[1]=4*10=40
//v=40
//o[]=201
//e[2]+e[3]=5+3=8
//e[0]*e[1]=4*5=20
//e[1]+e[2]=20+8=28
//v=28
//o[]=210
//e[2]+e[3]=5+3=8
//e[1]+e[2]=5+8=13
//e[0]*e[1]=4*13=52
//v=52
//maxv=70
//