大致題意:
題意很簡單,就是n個數,求最多兩兩交換S次,使前K個數的和最小
n <= 150, s = 1e9
思路:
顯然s >= n * n / 2 時總能把前K小的數交換到前K個位置
而且交換不交叉時是最優的,比如Ak 與 A(k+x)交換, 接下來Ak-1只能A(k+y)(y > x) 交換,總是最優的
這樣每次交換的代價是j - i,再增加一維可行位置保證不交叉,這樣就是S容量的揹包問題
//package ok;
import java.math.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import java.util.Arrays;
public class a {
public static void main(String args[]) {
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int n = in.nextInt();
int k = in.nextInt();
int s = in.nextInt();
int[] a = new int[n + 100];
for (int i = 1; i <= n ; i++) a[i] = in.nextInt();
if(s >= n * (n - 1) / 2) {
Arrays.sort(a, 1, n + 1);
int ans = 0;
for(int i = 1; i <= k; i ++) ans += a[i];
out.println(ans);
out.flush();
return ;
}
int [][][]dp = new int[n + 10][s + 10][2];
int ans = 0;
for(int i = 1; i <= k; i ++) ans += a[i];
for(int i = 1; i <= k; i ++) {
int cur = i & 1;
for(int j = n; j >= k + 1; j --)
for(int c = 0; c <= s; c ++) {
dp[j][c][cur] = Math.max(dp[j+1][c][cur], dp[j][c][cur ^ 1]);
if( c >= j - i && a[j] < a[i] )
dp[j][c][cur] = Math.max(dp[j][c][cur], dp[j + 1][c - (j - i)][cur ^ 1] + a[i] - a[j]);
}
}
out.println(ans - dp[k + 1][s][k & 1]);
out.flush();
}
static class Scanner {
BufferedReader br;
StringTokenizer st;
public Scanner(InputStream in) {
br = new BufferedReader(new InputStreamReader(in));
eat("");
}
private void eat(String s) {
st = new StringTokenizer(s);
}
public String nextLine() {
try {
return br.readLine();
} catch (IOException e) {
return null;
}
}
public boolean hasNext() {
while (!st.hasMoreTokens()) {
String s = nextLine();
if (s == null)
return false;
eat(s);
}
return true;
}
public String next() {
hasNext();
return st.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
public int[] nextIntArray(int n) {
int[] is = new int[n];
for (int i = 0; i < n; i++) {
is[i] = nextInt();
}
return is;
}
public long[] nextLongArray(int n) {
long[] ls = new long[n];
for (int i = 0; i < n; i++) {
ls[i] = nextLong();
}
return ls;
}
public double[] nextDoubleArray(int n) {
double[] ds = new double[n];
for (int i = 0; i < n; i++) {
ds[i] = nextDouble();
}
return ds;
}
public BigInteger[] nextBigIntegerArray(int n) {
BigInteger[] bs = new BigInteger[n];
for (int i = 0; i < n; i++) {
bs[i] = nextBigInteger();
}
return bs;
}
public int[][] nextIntMatrix(int row, int col) {
int[][] mat = new int[row][];
for (int i = 0; i < row; i++) {
mat[i] = nextIntArray(col);
}
return mat;
}
public long[][] nextLongMatrix(int row, int col) {
long[][] mat = new long[row][];
for (int i = 0; i < row; i++) {
mat[i] = nextLongArray(col);
}
return mat;
}
public double[][] nextDoubleMatrix(int row, int col) {
double[][] mat = new double[row][];
for (int i = 0; i < row; i++) {
mat[i] = nextDoubleArray(col);
}
return mat;
}
public BigInteger[][] nextBigIntegerMatrix(int row, int col) {
BigInteger[][] mat = new BigInteger[row][];
for (int i = 0; i < row; i++) {
mat[i] = nextBigIntegerArray(col);
}
return mat;
}
}
}