P1220 关路灯区间dp

做了不少dp,这个题一眼就看出是区间dp来了,不过推了一段时间发现不知道怎么推出状态,最后还是看了题解。这个题是从一个区间的左右两边向这个区间来推。

详细解释看代码吧

// let me get FY

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

using namespace std;

const int maxn = 110;

int a[maxn]; //存位置
int b[maxn]; // 存功率
int sum[maxn]; // 存前几个灯的总功率
int dp[maxn][maxn][2]; // dp区间和两个状态,一个是关完这个区间灯人在左边,另一个是关完这
//个区间灯人在右边

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    memset(dp, 0x3f, sizeof(dp));
    for(int i = 1; i <= n; i++)
    {
        scanf("%d%d",&a[i], &b[i]);
        sum[i] = sum[i - 1] + b[i];
       // printf("%d\n", sum[i]);
    }
    dp[m][m][0] = dp[m][m][1] = 0;
    for(int l = 2; l <= n; l++) // 区间长度
    {
        for(int i = 1; i <= n - l + 1; i++)
        {
            int j = l + i - 1;
           // printf("%d\n", sum[i] + sum[n] - sum[j]);
            dp[i][j][0] = min(dp[i + 1][j][0] + (a[i + 1] - a[i])* (sum[i] + (sum[n] - sum[j])), dp[i + 1][j][1] + (a[j] - a[i]) * (sum[i] + (sum[n] - sum[j])));
            dp[i][j][1] = min(dp[i][j - 1][0] + (a[j] - a[i]) * (sum[i - 1] + (sum[n] - sum[j - 1])), dp[i][j - 1][1] + (a[j] - a[j - 1]) * (sum[i - 1] + (sum[n] - sum[j - 1])));
// 对于关这个区间的灯有两种关法, 关左边和关右边,关左边有两种递推状态,一个是上一个区间
//关灯结束在左边,直接去关这个灯,另一个是在这个区间的右边,折返回来关这个灯,关右边同理
        }
    }
    int ans = min(dp[1][n][0], dp[1][n][1]); // 最后可能的两种状态取最小值
    printf("%d\n", ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值