您的位置:首页 > 其它

HDU 4283 You Are the One(区间DP)

2016-04-08 20:09 483 查看
题目链接:点击打开链接

思路: 经典区间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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm-icpc HDU 区间DP