입력의 크기가 작으면 언제나 브루트포스나 혹시 가능하다면 DP를 생각해봅니다. 함수의 인자로 , 까지 넣었을 때 cache배열의 크기는 입니다. 여기에 현재 더러운 정도인 를 추가하는데, 최대 더러워질 수 있는 정도가 이므로 차원 함수를 정의할 수 있습니다.
번째 날에 할 수 있는 선택은 청소를 하거나(아직 횟수가 남아있다면) 하지 않거나 입니다. 함수 하나의 시간 복잡도는 이므로 총 의 시간복잡도로 해결할 수 있습니다.
public class Main {
static int N;
static int[] S;
static int[][][] cache;
// i번째 날 부터 m번 골라 청소할 때 현재 더러운 정도가 k이면
// 각 사람들이 느낀 불쾌감의 최소 합
static int dp(int i, int m, int k) {
if (i == N) return 0;
if (cache[i][m][k] != 0) return cache[i][m][k];
int min = k * S[i] + dp(i + 1, m, k + S[i]);
if (m > 0) min = Math.min(min, k * S[i] + dp(i + 1, m - 1, 0));
return cache[i][m][k] = min;
}
static void reconstruct(int i, int m, int k, StringBuilder bw) {
if (i == N) return;
if (m > 0 && dp(i + 1, m - 1, 0) <= dp(i + 1, m, k + S[i])) {
bw.append(i + 1).append(" ");
reconstruct(i + 1, m - 1, 0, bw);
} else {
reconstruct(i + 1, m, k + S[i], bw);
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder bw = new StringBuilder();
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
N = Integer.parseInt(st.nextToken());
S = new int[N];
int M = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine(), " ");
for (int i = 0; i < N; i++) S[i] = Integer.parseInt(st.nextToken());
cache = new int[N][M + 1][N * 20 + 1];
bw.append(dp(0, M, 0)).append("\n");
reconstruct(0, M, 0, bw); bw.append("\n");
System.out.print(bw);
}
}
100 4
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
->380000
->20 40 60 80
모든 의 원소가 똑같다는 가정하에 을 늘리기만 한다면 점점 간격이 촘촘해지네요