2 条题解

  • 0
    @ 2025-10-8 16:56:37
    #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
      @ 2025-10-8 16:56:27
      #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

      *【动态规划:区间中间推】多边形[IOI1998]

      信息

      ID
      1370
      时间
      1000ms
      内存
      64MiB
      难度
      4
      标签
      递交数
      80
      已通过
      34
      上传者