hdu 4283 You Are the One(区间dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4283

题意:有队屌丝,每个人有一个愤怒值D,如果他是第K个上场,不开心指数就为(K-1)*D。但是边上有一个小黑屋(其实就是个堆栈)

可以先把人放置一下改变一下上场顺序,最后要得到总的不开心值最小。

数据比较小可以随意的套循环,简单的区间dp模版套3层for

设dp[i][j]表示从第i个人开始到第j个人愤怒总值是多少,可以想到

dp[i][j]=min(dp[i][j],dp[i+1][j]+a[i]*(k-i)(k表示i~j之间的数)+dp[k+1][j]+(k-i+1)*(sum[j]-sum[k])(sum表示前缀和))

这个转移方程很好理解,就是第i位的人要么先上要么放到后面。至于这个sum前缀和

为什么不会受到交换后影响,由于用到sum前缀和的都是移动后面的所以不会受到影响。

 

 

#include <iostream>
#include <cstring>
#include <string>
#define inf 1<<27;
using namespace std;
int a[110] , dp[110][110] , sum[110];
int main() {
    int t , n , ans = 0;
    cin >> t;
    while(t--) {
        ans++;
        cin >> n;
        memset(sum , 0 , sizeof(sum));
        memset(dp , 0 , sizeof(dp));
        for(int i = 1 ; i <= n ; i++) {
            cin >> a[i];
            sum[i] = sum[i - 1] + a[i];
            dp[i][i] = 0;
        }
        for(int i = 1 ; i <= n ; i++) {
            for(int j = i + 1 ; j <= n ; j++) {
                dp[i][j] = inf;
            }
        }
        for(int i = 1 ; i <= n - 1 ; i++) {
            for(int j = 1 ; j <= n && i + j <= n ; j++) {
                for(int k = j ; k <= i + j ; k++) {
                    dp[j][i + j] = min(dp[j][i + j] , dp[j + 1][k] + a[j] * (k - j) + dp[k + 1][j + i] + (k - j + 1) * (sum[i + j] - sum[k]));
                }
            }
        }
        cout << "Case #" << ans << ": " << dp[1][n] << endl;
    }
    return 0;
}
posted @ 2017-03-03 16:32  Gealo  阅读(151)  评论(0编辑  收藏  举报