持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情
2019河北省大学生程序设计竞赛——C-分治
C-分治
你是DEEP国的大军师,辅佐一个非常有野心的国王,这位国王非常有野心,他计划攻占 n 个国家。在地图上,这些国家排成一行。 探子已经查明,当攻打一个国家 i 时,为了防止国家间的联合对抗,需要给该国家周围,所有未被攻占的国家支付costicost_icosti 个金币,即对于国家 i,它左侧第一个已被攻打的国家为 l,右侧第一个已被攻打的国家为 r,则他需要给[l+1,i-1] 和 [i+1,r-1] 之间的国家支付金币。如果 l 不存在,则需要给 [1, i-1] 之间的所有国家支付金币;若 r 不存在,则需要给 [i+1,n] 之间的所有国家支付金币。
现在,你的下属已经给你提供了每个国家需要支付金币的数量。为了满足国王的野心,你需要计算出攻占完所有国家需要的最小花费。
输入描述:
第一行是一个整数 T,代表接下来有T组数据。
接下来每组数据
第一行有一个整数 n,代表要攻占的国家数目。
第二行共 n 个整数,代表攻占每个国家前,需要支付给其周围未被攻占国家 costi个金币。
1≤T≤50,1≤n≤,1≤costi≤10000
输出描述:
对于每组数据输出一行,代表需要支付的最小花费。
输入
2
1
1
3
1 1 2
输出
0
2
问题解析
区间DP。
二维状态数组f,f[i] [j]表示攻打第i~第j个国家,所需的最小花费为f[i] [j],f[i] [i]=0。
那么攻打i~j之间的国家k时,就有:*f[i] [j]=min(f[i] [j],f[i] [k-1]+f[k+1] [j]+(j-i)a[k]) ,其中a[k]是攻打第k个国家时需要给其它国家的金币,要给金币的国家数为i到j中除了k以外的全部国家,所以为:j-i。
考虑边界问题:
当我们要攻打第i个国家时:*f[i] [j]=min(f[i] [j],f[i+1] [j]+(j-i)a[i]) ;
攻打第j个国家时:*f[i] [j]=min(f[i] [j],f[i] [j-1]+(j-i)a[j]) ;
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 105;
int f[N][N], a[N], n;
void solve()
{
cin >> n;
for (int i = 0; i <= n; i++)
for (int j = 0; j <= n; j++)
{
f[i][j] = 1e9;
if (i == j)f[i][j] = 0;
}
for (int i = 1; i <= n; i++)cin >> a[i];
for (int len = 2; len <= n; len++)
{
for (int i = 1; i <= n - len + 1; i++)
{
int j = i + len - 1;
for (int k = i + 1; k < j; k++)
{
f[i][j] = min(f[i][j], f[i][k - 1] + f[k + 1][j] + (j - i) * a[k]);
}
f[i][j] = min(f[i][j], f[i][j - 1] + (j-i) * a[j]);
f[i][j] = min(f[i][j], f[i + 1][j] + (j-i) * a[i]);
}
}
cout << f[1][n] << endl;
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}