Alibaba UVA - 1632(区间dp+滚动数组)

博客探讨了在解决Alibaba UVA 1632问题时如何应用区间动态规划(DP)和滚动数组进行内存优化。作者指出,区间DP无需纠结起点,而是通过递增区间长度进行转移。文章强调,在使用滚动数组时避免使用刷表法以简化处理。

题目链接:点击打开链接

题目思路:有点久没写区间dp了,居然在纠结选哪一个作为起点,被自己蠢死,对于这道题来说根本不用关心这个问题,因为区间dp本来就枚举了每一个从小到大的区间,想通这一点,剩下的就很无脑了,唯一需要学习的就是这里用滚动数组优化内存的方法,对于区间dp我们可以发现每一次转移都这跟上一次区间长度有关,也就是用区间长度的递增来递推的,那么就很容易知道前面的长度基本上没什么用了,所以可以用滚动数组,另外用滚动数组的时候还是不要用刷表法好。。不好处理

无滚动数组版本:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstring>
#include<iostream>
#include<sstream>
#include<cmath>
#include<vector>
#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
const int maxn = 1e7+6;
int dp[10000+5][10000+5][2];
int n,m;
int a[10000+5];
int b[10000+5];
int main()
{
    while(~scanf("%d",&n)){
        for(int i = 1;i<=n;i++){
            scanf("%d%d",&a[i],&b[i]);
        }
        //memset(dp,INF,sizeof(dp));
        for(int i = 1;i<=n;i++){
            dp[i][i][0] = dp[i][i][1] = 0;
        }
        for(int len = 0;len<=n;len++){
            for(int i = 1;i<=n;i++){

                int j = i+len;
                if(j>n)
                    continue;
                if(i-1>=1){
                    dp[i-1][j][0] = min(dp[i][j][0]+a[i]-a[i-1],dp[i][j][1]+a[j]-a[i-1]);
                    if(dp[i-1][j][0]>=b[i-1])
                        dp[i-1][j][0] = INF;
                   // cout<<dp[i-1][j][0]<<' '<<i-1<<' '<<j<<endl;
                }
                if(j+1<=n){
                    dp[i][j+1][1] = min(dp[i][j][0]+a[j+1]-a[i],dp[i][j][1]+a[j+1]-a[j]);
                    if(dp[i][j+1][1]>=b[j+1])
                        dp[i][j+1][1] = INF;
                   // cout<<dp[i][j+1][1]<<' '<<i<<' '<<j+1<<endl;
                }
            }
        }
        int ans = min(dp[1][n][0],dp[1][n][1]);
        if(ans==INF)
            puts("No solution");
        else
            printf("%d\n",ans);
    }

}
滚动数组版本:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstring>
#include<iostream>
#include<sstream>
#include<cmath>
#include<vector>
#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
const int maxn = 1e7+6;
int dp[10000+5][2][2];
int n,m;
int a[10000+5];
int b[10000+5];
int main()
{
    while(~scanf("%d",&n)){
        for(int i = 1;i<=n;i++){
            scanf("%d%d",&a[i],&b[i]);
        }
        memset(dp,INF,sizeof(dp));
        for(int i = 1;i<=n;i++){
            dp[i][0][0] = dp[i][0][1] = 0;
        }
        int cur = 0;
        for(int len = 1;len<n;len++){
                cur ^=1;
            for(int i = 1;i<=n-len;i++){
                int j = i+len;
                    if(i+1<=n){
                    dp[i][cur][0] = min(dp[i+1][cur^1][0]+a[i+1]-a[i],dp[i+1][cur^1][1]+a[j]-a[i]);
                    if(dp[i][cur][0]>=b[i])
                        dp[i][cur][0] = INF;
                    }
                   // cout<<dp[i-1][j][0]<<' '<<i-1<<' '<<j<<endl
                   if(j-1>=0){
                    dp[i][cur][1] = min(dp[i][cur^1][0]+a[j]-a[i],dp[i][cur^1][1]+a[j]-a[j-1]);
                    if(dp[i][cur][1]>=b[j])
                        dp[i][cur][1] = INF;
                   }
                   // cout<<dp[i][j+1][1]<<' '<<i<<' '<<j+1<<endl
            }
        }
        int ans = min(dp[1][cur][0],dp[1][cur][1]);
        if(ans==INF)
            puts("No solution");
        else
            printf("%d\n",ans);
    }

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值