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;
}
思路: 经典区间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;
}
相关文章推荐
- 【HDU 5366】The mook jong 详解
- 【HDU 2136】Largest prime factor 详细图解
- 【HDU 1568】Fibonacci 数学公式 详解
- HDU 1568
- HDU1290
- HDU1568(Fobonacci公式)
- HDU ACM Step 2.2.2 Joseph(约瑟夫环问题)
- HDU 1405
- HDU 1297
- hdu 1205
- hdu 2087
- hdu 1016
- HDU 4898 The Revenge of the Princess’ Knight ( 2014 Multi-University Training Contest 4 )
- HDU 5592 ZYB's Premutation 线段树(查找动态区间第K大)
- HDU 5240 Exam (好水的题)
- HDU5237 Base64 大模拟
- HDU 1000
- HDU 1001
- 2015-11-11 hdu新生赛 A题(AC)
- 2015-11-11 hdu新生赛 C题(结束后一发AC)