分段动态规划(SOJ 1162)

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;
}
View Code

 

猜你喜欢

转载自www.cnblogs.com/ClearMoonlight/p/10508344.html