POJ 1179 Polygon(区间DP) -补充

本文深入探讨了区间DP技术,并将其与石子合并问题进行对比,重点介绍了如何利用动态规划解决环形特征问题及代码实现细节。同时,文章详细解释了动态规划四边形优化原理及其应用,通过实例分析帮助读者理解复杂概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题是典型的区间DP,老师给我们小学期的DP就这么难。。。。。现在才能刷完。

这道题其实可以跟石子合并问题归为一类。(三种.....)

不过这里要注意一点就是有乘法运算,乘法可能将两个最小的数字变为最大的,所以在dp过程中要记录最大最小值。自认为代码还比较能看。

这里还要输出起初去掉的边,DP完后直接扫一遍。(环形特征,注意取模)

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#define inf (1<<30)
using namespace std;
typedef long long ll;
const int maxn=10+100;
int dp[maxn][maxn][2];
char edge[maxn];
int number[maxn];
int N,M;
int main()
{
    while(~scanf("%d",&N))
    {
        for(int i=0;i<N;i++)
            cin>>edge[i]>>number[i];
        edge[N]=edge[0];
        memset(dp,0,sizeof(dp));
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++)
                if(i==j)
                    dp[i][j][0]=dp[i][j][1]=number[i];
                else dp[i][j][0]=-inf,dp[i][j][1]=inf;
        int ans=-inf;

            for(int len=1;len<N;len++)
                for(int i=0,j=i+len;i<N;i++,j++)
                {
                    for(int k=i;k<j;k++)
                    {
                        if(edge[(k+1)%N]=='t')
                            dp[i%N][j%N][0]=max(dp[i%N][j%N][0],dp[i%N][k%N][0]+dp[(k+1)%N][j%N][0]),
                            dp[i%N][j%N][1]=min(dp[i%N][j%N][1],dp[i%N][k%N][1]+dp[(k+1)%N][j%N][1]);
                        else
                            dp[i%N][j%N][0]=max(dp[i%N][j%N][0],dp[i%N][k%N][0]*dp[(k+1)%N][j%N][0]),
                            dp[i%N][j%N][0]=max(dp[i%N][j%N][0],dp[i%N][k%N][1]*dp[(k+1)%N][j%N][1]),
                            dp[i%N][j%N][1]=min(dp[i%N][j%N][1],dp[i%N][k%N][1]*dp[(k+1)%N][j%N][1]),
                            dp[i%N][j%N][1]=min(dp[i%N][j%N][1],dp[i%N][k%N][0]*dp[(k+1)%N][j%N][1]),
                            dp[i%N][j%N][1]=min(dp[i%N][j%N][1],dp[i%N][k%N][1]*dp[(k+1)%N][j%N][0]);
                        if(len==N-1)
                            ans=max(dp[i][j%N][0],ans);
                    }
                }
        printf("%d\n",ans);
        int aa[100];int k=0;
        for(int i=0;i<N;i++)
            if(dp[i][(i-1+N)%N][0]==ans)
                aa[k++]=i+1;
        for(int i=0;i<k;i++)
            if(i==k-1) printf("%d\n",aa[i]);
            else printf("%d ",aa[i]);
    }
    return 0;
}

更新:

这道题做了以后发现石子合并问题的三种中第三种跟这个很像,于是学习一下。

问题:一堆石子,每个石子都有其价值要求两两合并,使得价值最大/最小。

1.每次的石子都任意选取。 跟哈夫曼一样。

2.排成一条线,每次只能选取相邻的。子集覆盖括号匹配问题,使用矩阵链乘的DP方案。


3.直线变为环。这个是关键点。也于本题相似。其思路是换了一种dp[i][j]的表示意思,即从i开始合并j个的最小价值。

其本质并未变,与原先意思也差不多。代码则是j在外层表示长度,i表示起始位置。(用之前的表示也没什么不妥的,就是改变一个内循环的次数到n即可)




动态规划四边形优化:

百度知道的回答     百度文库的论文

1.满足四边形不等式

w[i,j] + w[i‘,j’] <= w[i‘,j] + w[i,j’]  (i<=i‘<j<=j’) 

2.满足区间包含单调性

 w[i’,j]  <= w[i,j’] (i<=i‘<j<=j’) 
那么对于
m[i,j]=min{m[i,k-1]+m[k,j]+w[i,j]} (i<k<=j)

如果w[i,j]满足四边形不等式和区间包含单调性,那么m[i,j]也满足四边形不等式。 用s[i,j]表示m[i,j]的决策,如果函数m[i,j]满足四边形不等式,则函数s[i,j]满足单调性,即决策单调性: s[i,j]<=s[i,j+]<=s[i+1,j+1]。

其证明我是没看懂。掌握:当m[i,j]=min{m[i,k-1]+m[k,j]+w[i,j]} (i<k<=j) 中w[i,j]满足两个性质的时候,k的取值不用全部枚举。只需从s[i][j-1]~s[i+1][j]枚举即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值