多边形游戏——区间dp

此题类似石子合并,将环状多边形转换成链,由n转入2*n+1个字符。

总数量不能变,所以一点一点向后推移;

先进行一个循环,决定去掉那条边,再加n,向后推移;

f[i][j],表示从i到j的最优解;

每一个点必定是由两个点组成,so,在i,j区间枚举分割点,注意分割点不能等于j;

因为这题中,数字有正有负,必然要考虑负负得正的情况

例如,-1000*-1000=1000000 100*100=10000 而1000000>10000,但-1000却小于100;

所以每一次合并必然要考虑最小值和最大值;

如果下一次合并时,符号是‘+’,那就直接将最大值和最小值相加;

若是‘*’,那就将大*大,大*小,小*大,小*小四种比较一下,寻找最大值和最小值;

 

 

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int n,shu[150],f[150][150][3],sum[150][150],ff[150]={0},ma,mb,a,b,c,d;
char fu[150];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>fu[i]>>shu[i];//先输入符号,在输入数字
    }
    for(int i=n+1;i<=2*n;i++)
    {
        shu[i]=shu[i-n];
        fu[i]=fu[i-n];
    }
    for(int i=1;i<=n;i++)
    {
        for(int o=1;o<=2*n;o++)
        {
            for(int p=1;p<=2*n;p++)
            {
                f[o][p][1]=-9999999;//求大值,初始化最小
                f[o][p][2]=9999999;//求小值,初始化最大
            }
        }
        for(int q=1;q<=2*n;q++)//初始化区间dp
        {
            f[q][q][1]=shu[q];
            f[q][q][2]=shu[q];
            if(fu[q+1]=='t')
            {
                f[q][q+1][1]=shu[q]+shu[q+1];
                f[q][q+1][2]=shu[q]+shu[q+1];
            }
            if(fu[q+1]=='x')
            {
                f[q][q+1][1]=shu[q]*shu[q+1];
                f[q][q+1][2]=shu[q]*shu[q+1];
            }
        }
        for(int l=2;l<=n;l++)
        {
            for(int j=i;j<=i+n-l;j++)
            {
                int k=j+l-1;
                for(int x=j;x<k;x++)//一定要小于k,因为后面有x+1;
                {
                    if(fu[x+1]=='t'&&f[j][k][1]<f[j][x][1]+f[x+1][k][1])f[j][k][1]=f[j][x][1]+f[x+1][k][1];
                    if(fu[x+1]=='t'&&f[j][k][2]>f[j][x][2]+f[x+1][k][2])f[j][k][2]=f[j][x][2]+f[x+1][k][2];
                    if(fu[x+1]=='x')
                    {
                        a=f[j][x][1]*f[x+1][k][1];
                        b=f[j][x][2]*f[x+1][k][1];
                        c=f[j][x][1]*f[x+1][k][2];
                        d=f[j][x][2]*f[x+1][k][2];
                        f[j][k][1]=max(max(max(a,b),max(c,d)),f[j][k][1]);
                        f[j][k][2]=min(min(min(a,b),min(c,d)),f[j][k][2]);
                    }
                }
            }
        }
        ff[i]=f[i][i+n-1][1];
    }
    ma=-1000000;
    for(int i=1;i<=n;i++)//寻找最大值
    {
        if(ma<ff[i])
        {
            ma=ff[i];
            mb=i;
        }
    }
    cout<<ma<<endl;
    for(int i=1;i<=n;i++)
    {
        if(ff[i]==ma)
        {
            cout<<i<<" ";//输出可以断第几个
        }
    }
}
/*
4                                      120
x 2 x 3 x 4 x 5                   1 2 3 4


6                                                     10000
x -10 x -10 x -10 t 10 t 10 t 10          6


7                                                       300000
x -10 x -10 x -10 x -10 t 10 t 10 t 10   5
以上是三组测试数据*/    

 以上是个人见解,,如有不妥请评论区发表意见

以下是改进后的代码

#include<bits/stdc++.h>
using namespace std;
int n,num[105],dp1[105][105],dp2[105][105],maxn[55],maxx;
char fu[105];
int main()
{
	memset(dp1,0x8f,sizeof(dp1));
	memset(dp2,0x3f,sizeof(dp2));
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>fu[i]>>num[i];
		fu[n+i]=fu[i];
		num[n+i]=dp1[i][i]=dp1[n+i][n+i]=dp2[i][i]=dp2[n+i][n+i]=num[i];
	}
	for(int o=1;o<=n;o++){
		for(int l=2;l<=n;l++){
			for(int i=o;i<=o+n-l;i++){
				int j=i+l-1;
				for(int k=i+1;k<=j;k++){
					int a,b,c,d;
					if(fu[k]=='t'){
						a=dp1[i][k-1]+dp1[k][j];
						b=dp2[i][k-1]+dp2[k][j];
						dp1[i][j]=max(dp1[i][j],a);
						dp2[i][j]=min(dp2[i][j],b);
					}
					if(fu[k]=='x'){
						a=dp1[i][k-1]*dp1[k][j];
						b=dp1[i][k-1]*dp2[k][j];
						c=dp2[i][k-1]*dp2[k][j];
						d=dp2[i][k-1]*dp1[k][j];
						dp1[i][j]=max(dp1[i][j],max(a,max(b,max(c,d))));
						dp2[i][j]=min(dp2[i][j],min(a,min(b,min(c,d))));
					}
				}
			}
		}
		maxn[o]=dp1[o][o+n-1];
		maxx=max(maxx,dp1[o][o+n-1]);
	}
	cout<<maxx<<endl;
	for(int i=1;i<=n;i++){
		if(maxn[i]==maxx)
			cout<<i<<" ";
	}
}

 

posted @ 2019-08-02 16:44  fengwu2005  阅读(432)  评论(1编辑  收藏  举报