2 条题解
-
0
#include<bits/stdc++.h> //by:hansang using namespace std; const int N=110, M=-32769; // M比数据最小值小一点,-M比数据最大值大一点 int n, a[N], f1[N][N], f2[N][N]; bool b[N]; // a[i]是第 i个点的值,b[i]是第 i条边是什么符号 // f1[i][j]是 i到 j合并到只剩一个端点最大的值,f2[i][j]是 i到 j合并到只剩一个端点最小的值 int mymax(int a1, int a2, int a3, int a4, int a5) {return max(a1, max(a2, max(a3, max(a4, a5))));} int mymin(int a1, int a2, int a3, int a4, int a5) {return min(a1, min(a2, min(a3, min(a4, a5))));} int main() { scanf("%d", &n); for(int i=1; i<=n; i++) { char s[2]; scanf("%s%d", s, &a[i]); if(s[0]=='t') b[i]=0; else b[i]=1; //是加号的话为 0,是乘号的话为 1 a[n+i]=a[i]; b[i+n]=b[i]; //断环为链,就是复制一段在后面 } for(int i=1; i<=2*n; i++) for(int j=1; j<=2*n; j++) f1[i][j]=M, f2[i][j]=-M; //初始化,赋值成最小和最大值,用 M是为了防止溢出 (但因为本题数据范围的缘故,用 0x3f也没问题) for(int i=1; i<=2*n; i++) f1[i][i]=f2[i][i]=a[i]; // 从 i到 i的最大和最小值都是 a[i] for(int L=2; L<=n; L++) //枚举长度 for(int i=1; i<=2*n-L+1; i++) //开头 { int j=i+L-1; //结尾 for(int k=i; k<j; k++) { if(b[k+1]==1) //当是乘法运算时 (用 k+1是因为 b[k+1]才是 a[k]与 a[k+1]之间的边,而 k<j,加 1也不会大于 2*n) { f1[i][j]=mymax(f1[i][j], f1[i][k]*f1[k+1][j], f1[i][k]*f2[k+1][j], f -
0
#include<bits/stdc++.h> //by:hansang using namespace std; const int N=110, M=-32769; // M比数据最小值小一点,-M比数据最大值大一点 int n, a[N], f1[N][N], f2[N][N]; bool b[N]; // a[i]是第 i个点的值,b[i]是第 i条边是什么符号 // f1[i][j]是 i到 j合并到只剩一个端点最大的值,f2[i][j]是 i到 j合并到只剩一个端点最小的值 int mymax(int a1, int a2, int a3, int a4, int a5) {return max(a1, max(a2, max(a3, max(a4, a5))));} int mymin(int a1, int a2, int a3, int a4, int a5) {return min(a1, min(a2, min(a3, min(a4, a5))));} int main() { scanf("%d", &n); for(int i=1; i<=n; i++) { char s[2]; scanf("%s%d", s, &a[i]); if(s[0]=='t') b[i]=0; else b[i]=1; //是加号的话为 0,是乘号的话为 1 a[n+i]=a[i]; b[i+n]=b[i]; //断环为链,就是复制一段在后面 } for(int i=1; i<=2*n; i++) for(int j=1; j<=2*n; j++) f1[i][j]=M, f2[i][j]=-M; //初始化,赋值成最小和最大值,用 M是为了防止溢出 (但因为本题数据范围的缘故,用 0x3f也没问题) for(int i=1; i<=2*n; i++) f1[i][i]=f2[i][i]=a[i]; // 从 i到 i的最大和最小值都是 a[i] for(int L=2; L<=n; L++) //枚举长度 for(int i=1; i<=2*n-L+1; i++) //开头 { int j=i+L-1; //结尾 for(int k=i; k<j; k++) { if(b[k+1]==1) //当是乘法运算时 (用 k+1是因为 b[k+1]才是 a[k]与 a[k+1]之间的边,而 k<j,加 1也不会大于 2*n) { f1[i][j]=mymax(f1[i][j], f1[i][k]*f1[k+1][j], f1[i][k]*f2[k+1][j], f2[i][k]*f1[k+1][j], f2[i][k]*f2[k+1][j]); //因为可能两个负数相乘反而是最大值了,所以 f1[i][j]要等于 max(最大乘最大,最大乘最小,最小乘最大,最小乘最小) f2[i][j]=mymin(f2[i][j], f1[i][k]*f1[k+1][j], f1[i][k]*f2[k+1][j], f2[i][k]*f1[k+1][j], f2[i][k]*f2[k+1][j]); // f2[i][j]同理,不过是 min } else //当时加法运算时 { f1[i][j]=max(f1[i][j], f1[i][k]+f1[k+1][j]); f2[i][j]=min(f2[i][j], f2[i][k]+f2[k+1][j]); //加法最大值只能是最大加最大,最小值只能是最小加最小 } } } int ans=M; // ans赋值最小值 for(int i=1; i<=n; i++) ans=max(ans, f1[i][i+n-1]); //求从不同的地方开始的长度为 n的答案的最大值 printf("%d\n", ans); //输出 for(int i=1; i<=n; i++) if(f1[i][i+n-1]==ans) printf("%d ", i); //从 i开始就是第 i条边没算到,也就是"删除"了,当从 i开始时答案仍旧是最大的,就代表可以"删除" i,直接输出 printf("\n"); return 0; }
- 1
信息
- ID
- 1370
- 时间
- 1000ms
- 内存
- 64MiB
- 难度
- 4
- 标签
- 递交数
- 80
- 已通过
- 34
- 上传者