HDU 4283 You Are the One(区间DP)

101 篇文章 0 订阅
5 篇文章 0 订阅

题目链接:点击打开链接

思路: 经典区间DP, 用区间d[l][r]表示, 当前[l, r]区间的最优解。  那么对于当前区间, 左端点的行为决定了状态的转移, 那么编号l的人是否进小黑屋, 第几个进小黑屋呢。  我们再用一重循环枚举, l是[l, r]区间中第几个出场的, 那么他前面有多少人,贡献就增加几个a[l]。 假设, 是第k个出场的, 那么答案需要累加上它前边的人的贡献:(k - l) * a[l], 因为区间[l, k]的人都在区间[k+1, r]的人前面, 所以贡献还要加上(k - l + 1) * (sum[r] - sum[k])。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const ld eps = 1e-9, PI = 3.1415926535897932384626433832795;
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
// & 0x7FFFFFFF
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 100 + 10;
int T,n,m,d[maxn][maxn],vis[maxn][maxn],kase = 0,a[maxn],sum[maxn];
int dp(int l, int r) {
    int& ans = d[l][r];
    if(l >= r) return 0;
    if(vis[l][r] == kase) return ans;
    vis[l][r] = kase;
    ans = INF;
    for(int i = l; i <= r; i++) {
        ans = min(ans, dp(l+1, i) + dp(i+1, r) + a[l] * (i - l) + (i - l + 1) * (sum[r] - sum[i]));
    }
    return ans;
}
void init() {
    for(int i = 1; i <= n; i++) {
        sum[i] = sum[i-1] + a[i];
    }
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        for(int i = 1; i <= n; i++) {
            scanf("%d",&a[i]);
        }
        init();
        ++kase;
        int ans = dp(1, n);
        printf("Case #%d: %d\n",kase, ans);
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值