SOJ 1162: I-Keyboard http://acm.scu.edu.cn/soj/problem.action?id=1162
Given a string $S$ with length $L$ in which each character has a frequency $F[i], 0\le i<L$, the target is to partition $S$ into $K$ segments satisfying that the sum of products is minimized. For each segment, each character has a position $P[i]$ from $1$ to its length.
String: $S[0], \dots, S[i_{1}]$ | $S[i_{1}+1], \dots, S[i_{2}]$ | $\dots$ | $S[i_{K-1}+1], \dots, S[i_{K}]$ $(S[L-1])$
Segment: $1$ | $2$ | $\dots$ | $K$
Position: $1, \dots, i_{1}+1$ | $1, \dots, i_{2}-i_{1}$ | $\dots$ | $1, \dots, i_{K}-i_{K-1}$
Frequency: $F[0], \dots, F[i_{1}]$ | $F[i_{1}+1], \dots, F[i_{2}]$ | $\dots$ | $F[i_{K-1}+1], \dots, F[i_{K}]$ $(F[L-1])$
The definition of sum of products cost is as follows:
$cost=\Sigma P[i]*F[i].$
This problem is one dynamic programming problem. The optimal substructure is that: if $cost(K, i_{K})$ is the optimal solution of string $S[0, \dots, i_{K}]$ with $K$ segments, then $cost(K-1, i_{K-1})$ is the optimal solution of string $S[0, \dots, i_{K-1}]$ with $K-1$ segments. Define $cost[i][j]$ as the optimal solution for string $S[0, \dots, j]$ with $i$ segments, then we have the state transition equation:
$cost[i][j]=\min\{cost[i-1][k]+\sum_{t=k+1}^{j}(t-k)*F[t], k=i-1, \dots, j-1\}.$
That is, serve each $S[k+1, \dots, j], k=i-1, \dots, j-1$ as the $i$-th segment. Here there is one point we need to pay attention to, the calculation of $\sum_{t=k+1}^{j}(t-k)*F[t]$. Notice that
$\sum_{t=k+1}^{j}(t-k)*F[t]=\sum_{t=k+1}^{j}t*F[t]-k\sum_{t=k+1}^{j}F[t]$,
thus we can use the cumulative sum technique to deal with it.
The whole code is as follows:
#include<iostream> using namespace std; char key[95]; char letter[95]; int weight[95]; int cost[95][95]; int flag[95][95]; int position[95]; int sum1[95]; int sum2[95]; int main() { int T; scanf("%d",&T); int K,L; int i,j,k,t; int tarVal; int temp; for(t=1;t<=T;t++) { scanf("%d%d",&K,&L); scanf("%s",key); scanf("%s",letter); scanf("%d",&weight[0]); sum1[0]=weight[0]; sum2[0]=weight[0]; for(j=1;j<L;j++) { scanf("%d",&weight[j]); sum1[j]=sum1[j-1]+weight[j]*(j+1); sum2[j]=sum2[j-1]+weight[j]; } cost[0][0]=weight[0]; for(j=1;j<L;j++) cost[0][j]=sum1[j]; for(i=1;i<K;i++) for(j=i;j<L;j++) { tarVal=0x3f3f3f3f; for(k=i-1;k<=j-1;k++) { temp=cost[i-1][k]+sum1[j]-sum1[k]-(k+1)*(sum2[j]-sum2[k]); if(temp<tarVal) { tarVal=temp; flag[i][j]=k+1; } } cost[i][j]=tarVal; } temp=L-1; for(i=K-1;i>0;i--) { position[i]=flag[i][temp]; temp=position[i]-1; } position[0]=0; position[K]=L; printf("Keypad #%d:\n",t); for(i=0;i<K;i++) { printf("%c: ",key[i]); for(j=position[i];j<position[i+1];j++) printf("%c",letter[j]); printf("\n"); } printf("\n"); } return 0; }
原文地址:https://www.cnblogs.com/ClearMoonlight/p/10508344.html