poj 1179 $Polygon$(断环成链)

Polygon

V6nbEd.png

V6ul5R.png



\(solution:\)

upd:还是多讲一下,这道题基本上可以说是一道思维题、一道结论题、一道考验你动态规划基本功是否扎实的题目。因为这道题的数据范围很小,思考一下总能想到断环成链的(因为去处环形后效性的方法就两个,一个是断环成链,另一个就是将环等效成两次线性DP,但是后者有条件)。然后,这一题还有一个更重要的东西,他只涉及加法和乘法(注意这里有乘法),当我们使用动态规划时应该要注意它需要能从阶段的最优性得到答案的最优结果!以前我们使用动态规划时权值往往维护一个最大或最小值即可,但这一题不一样。

因为这一道题它有乘法还有负数!所以如果我们动态规划维护的是最大值,我用它乘上一个负数,那它就直接变成了一个较小值!所以我们如果要最优子结构能转移到最优答案,这个子结构还需要维护一个最小值(因为两个小的负数相乘可以得到一个大正数)!所以这一题最大最小对我们得出答案都有用(而且只需要他们两个即可,较小值比不过最小值)。这是这一题最难以突破的一个地方,想到之后就是一道结论题了。



\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int

using namespace std;

inline int min(int x,int y){
    if(x<y)return x;
    return y;
}
inline int max(int x,int y){
    if(x>y)return x;
    return y;
}

int n,t,m;
int a[105];
int ans[55];
bool b[105],s[105];

struct su{
    int x,y;
    inline void add(su i,su j){
        x=max(x,i.x+j.x);
        y=min(y,i.y+j.y);
    }
    inline void mul(su i,su j){
        x=max(x,i.x*j.x);
        x=max(x,i.y*j.y);
        y=min(y,i.y*j.y);
        y=min(y,i.x*j.y);
        y=min(y,i.y*j.x);
    }
}f[55][55];

inline int qr(){
    register char ch; register bool sign=0; rg res=0;
    while(!isdigit(ch=getchar())) if(ch=='-')sign=1;
    while(isdigit(ch)) res=res*10+(ch^48),ch=getchar();
    return sign?-res:res;
}

int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    n=qr(); char ch;
    for(rg i=1;i<=n;a[n+i]=a[i]=qr(),++i)
        cin>>ch,b[n+i]=b[i]=(ch=='x');
    for(rg o=1;o<=n;++o){ t=0;
        for(rg i=1;i<=n;++i)
            for(rg j=1;j<=n;++j)
                f[i][j].x=-inf,f[i][j].y=inf;
        for(rg i=o;i<o+n;i++)
            s[++t]=b[i+1],f[t][t].x=f[t][t].y=a[i];
        for(rg l=1;l<n;++l){
            for(rg i=1,j=i+l;j<=n;++i,++j){
                for(rg k=i;k<j;++k){
                    if(s[k])f[i][j].mul(f[i][k],f[k+1][j]);
                    else f[i][j].add(f[i][k],f[k+1][j]);
                }
            }
        }ans[o]=f[1][n].x; m=max(m,ans[o]);
    }printf("%d\n",m);
    for(rg i=1;i<=n;++i)
         if(ans[i]==m)printf("%d ",i);
    return 0;
}

转载于:https://www.cnblogs.com/812-xiao-wen/p/10999736.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值