0550-Dividing Snacks

問題概要

日本語なので略

解法

図のようにおかしの各場所に0か1を割り当てることを考える.

すると0と1の切り替わる場所で切断することが分かるので,
DP[いままで見た切断箇所の個数][0の個数][一つ前のマスの数値]=その最小コストのようにすることが出来る.
DP[i][j]に対する漸化式は
DP[i+1][j+1][0]=min(DP[i][j][0],DP[i][j][1]+cost[i])
DP[i+1][j][1]=min(DP[i][j][1],DP[i][j][0]+cost[i])
のようになる.初期条件はDP[0][0][0]=0.

このままではメモリが足りなくなるので,DP配列を偶奇で使い回す.

実装(C)

#include <stdio.h>
#include <string.h>
#define min(a,b) (a)>(b)?(b):(a)
int k[10000];
short dp[2][5101][2];

int main() {
	int N,i,j;
	scanf("%d",&N);
	for(i=0;i<N-1;i++)
		scanf("%d",&k[i]);
	memset(dp,0x7f,sizeof(dp));
	dp[0][0][0]=0;
	for(i=0;i<N;i++){
		int m=min(5009,i);
		for(j=0;j<=m;j++){
			dp[(i+1)&1][j+1][0]=min(dp[i&1][j][0],dp[i&1][j][1]+k[i]);
			dp[(i+1)&1][j][1]=min(dp[i&1][j][1],dp[i&1][j][0]+k[i]);
		}
		dp[i&1][0][0]=0x7f7f;
	}
	printf("%d\n",dp[N%2][N/2][0]);
	return 0;
}