A top-secret military base under the command of Colonel Zuev is expecting an inspection from the Ministry of Defence. According to the charter, each top-secret military base must include a top-secret troop that should... well, we cannot tell you exactly what it should do, it is a top secret troop at the end. The problem is that Zuev's base is missing this top-secret troop for some reasons.
The colonel decided to deal with the problem immediately and ordered to line up in a single line all n soldiers of the base entrusted to him. Zuev knows that the loquacity of the i-th soldier from the left is equal to qi. Zuev wants to form the top-secret troop using k leftmost soldiers in the line, thus he wants their total loquacity to be as small as possible (as the troop should remain top-secret). To achieve this, he is going to choose a pair of consecutive soldiers and swap them. He intends to do so no more than s times. Note that any soldier can be a participant of such swaps for any number of times. The problem turned out to be unusual, and colonel Zuev asked you to help.
Determine, what is the minimum total loquacity of the first k soldiers in the line, that can be achieved by performing no more than s swaps of two consecutive soldiers.
Input
The first line of the input contains three positive integers n, k, s (1 ≤ k ≤ n ≤ 150, 1 ≤ s ≤ 109) — the number of soldiers in the line, the size of the top-secret troop to be formed and the maximum possible number of swap operations of the consecutive pair of soldiers, respectively.
The second line of the input contains n integer qi (1 ≤ qi ≤ 1 000 000) — the values of loquacity of soldiers in order they follow in line from left to right.
Output
Print a single integer — the minimum possible total loquacity of the top-secret troop.
题目大意:
N个数,最多S次交换次数,每次能交换相邻两个数,问前k个数的最小总和是多少。
输入:
样例1
3 2 2
2 4 1
样例2
5 4 2
10 1 6 2 5
样例3
5 2 3
3 1 4 2 5
输出:
样例1
3
样例2
18
样例3
3
思路:dp
dp[i][j][k]表示前i个数放入j个,交换了k次(转移表达式挺巧妙的
当前i不选则有,dp[i][j][k] = dp[i-1][j][k]
若选dp[i][j][k] = min( dp[i][j][k] , dp[i-1][j-1][k-(i-j)] ) (第i个选,单i的交换次数为k-(i-j),实际上就是i距离当前长度j序列的距离
再用滚动数组优化一下就好了~
(有看到开二维数组dp的解法,不过不是很理解为了避免后效性,外层从大到小枚举,内层从小到大枚举
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(x,y) memset(x,y,sizeof(x))
#define INF 0x3f3f3f3f
#define int long long
using namespace std;
typedef long long ll;
const int N = 1e9+10;
int dp[2][160][160*160];//dp[i][j][k]表示考虑前i个数放入j个交换了k次的最小值
int a[160];
signed main()
{
IOS;
mst(dp,INF);
int n,k,s;
cin>>n>>k>>s;
_for(i,1,n) cin>>a[i];
dp[0][0][0] = 0;
dp[1][0][0] = 0;
_for(i,1,n)
{
int p = i & 1;
int q = 1^p;
mst(dp[i&1][0],0);
_for(j,1,i)
{
_for(k,0,i*j)
{
dp[p][j][k] = dp[q][j][k];
if( k >= i-j )
dp[p][j][k] = min( dp[p][j][k] , a[i] + dp[q][j-1][k-(i-j)]);
}
}
}
ll ans = INF;
_for( i,0,min(s,n*(n-1)/2) )
ans = min(ans,1ll * dp[n&1][k][i]);
cout<<ans<<endl;
}