UNISON - ZOJ 2685 dp

UNISON

Time Limit: 2 Seconds       Memory Limit: 65536 KB

A union is an instance of playing the same pitch or of playing in octave. We want to arrange new polyphonic music with three different monophonic music scores of arbitrary length. Each monophonic music score has only 7 tones, C(do), D(re), E(mi), F(fa), G(sol), A(la), B(si) with the same interval.

You can see polyphonic music X with three monophonic music scores (Music1, Music2, Music3) in Figure 1. Note that the lengths of Music1, Music2, and Music3 are 12, 12, 11, respectively. '&' is the symbol of a pause and means that no tone is played in that position. Music X is the same as playing 3 different monophonic music scores (Music1, 2, 3) simultaneously. The tones in each column of Figure-1 denote a set of tones to be played simultaneously in polyphonic music.

Figure 1: A newly arranged polyphonic music X with unison weight 7.

Let us define "unison" in this problem. A unison is an instance where the same tones are played simultaneously in a score. Thus, column1 = {A, F,A} and column2 = {C,C, F} are not unisons, so the music score X has only three unisons: column6 = {B,B,B}, column10 = {D,D,D}, and column12 = {A, A,&} . Formally, a column M = {x, y, z} is a unison, if M has three of the same tones or two of the same tones plus &. If x = y = z 6= '&', then the weight of the unison is 3. If M has two of the same tones and a single '&', then the weight of the column is 1. The sum of all unisons in a score is called the total unison weight. The following table shows the unison weight for each tone set.

Tones in a columnUnison weight
C C C3
D D D3
E E E3
......3
B B B3
C C &1
D D &1
......1
B B &1
All others0
Table 1: Unison weight table for the tones in a column.

The unison weight of score X in Figure-1 is 3 + 3 + 1 = 7. However, if we arrange X to get another music by inserting pause symbols smartly, then we can increase the total unison weight significantly. Figure 2 shows another arrangement Y with unison weight 25.

Figure 2: Another polyphonic music Y with unison weight 25.

You are asked to compute the maximal unison weight from three different music scores by optimally inserting '&' symbols in each score. One important constraint on inserting '&' is that you should not insert more than one consecutive & in a music score. See Figure 3 for this constraint. Also, you are not allowed to modify the tones (melody) or to change the sequence of tones. Keep in mind that your arrangement can only insert &'s separately to get a maximal unison.

Write a program that finds the maximal unison weight by using an optimal arrangement.

Figure 3: This arrangement is not allowed (infeasible arrangement) because Music2 includes more than one &.
.

Input

The input consists of T test cases. The number of test cases (T) is given on the first line of the input file. Each test case starts with three lines containing a string of monophonic music scores consisting of a symbol set = {C, D, E, F, G, A, B}. There is a blank line between test cases. The maximal length of each monophonic music score string is 100.

Output

For each test case, your program reports only one number, the maximal total unison weight of each testing case in a line. If there is no arrangement satisfying the constraint, then print -1 as the output. The following shows sample input and output for four test cases.

Sample Input

4
ABCDEF
BCDEFG
DEFGAB

GABBCDEACF
GAFGFCBBDEDD
AFAFGCEECDEDF

BCDEFGGADEF
BCDE
CDEFGABBA

GAGABDEDCGAFFAB
DAFFAGAEECCBA
GCBDAAEGEAGAFF

Sample Output

5
15
-1
14

题意:在三个字符串中加入&,使得三个字符串长度相同且得分最高,问最高的得分是多少。注意不能有两个相同的&。

思路:dp[i][j][k]表示三个字符串前i,j,k,组成的最大得分,我们用偶数2*i表示第i个字符,2*i+1表示前i个字符并且后面跟一个&的情况,这样就方便转移,并且排除非法情况。

AC代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[210][210][210],len[4],length[4];
char s[4][110],s2[110],s3[110];
int solve(int a,int b,int c)
{
    int ret=0;
    if(a&1)
      ret++;
    if(b&1)
      ret++;
    if(c&1)
      ret++;
    if(ret==3)
      return -1;
    if(ret==2)
      return 0;
    if(ret==0)
      if(s[1][a/2]==s[2][b/2] && s[1][a/2]==s[3][c/2])
        return 3;
    if(ret==1)
    {
        if((a&1) && s[2][b/2]==s[3][c/2])
          return 1;
        if((b&1) && s[1][a/2]==s[3][c/2])
          return 1;
        if((c&1) && s[1][a/2]==s[2][b/2])
          return 1;
    }
    return 0;
}
int main()
{
    int t,i,j,k,p,len1,len2,len3,val,ans;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,-1,sizeof(dp));
        dp[0][0][0]=0;
        for(i=1;i<=3;i++)
        {
            scanf("%s",s[i]+1);
            len[i]=strlen(s[i]+1);
            length[i]=len[i]*2+1;
        }
        for(i=1;i<=length[1];i++)
           for(j=1;j<=length[2];j++)
              for(k=1;k<=length[3];k++)
              {
                  val=solve(i,j,k);
                  if(val==-1)
                    continue;
                      if(dp[(i-1)/2*2][(j-1)/2*2][(k-1)/2*2]>=0)
                       dp[i][j][k]=max(dp[i][j][k],dp[(i-1)/2*2][(j-1)/2*2][(k-1)/2*2]+val);

                      if((i&1)==0 && dp[i-1][(j-1)/2*2][(k-1)/2*2]>=0)
                       dp[i][j][k]=max(dp[i][j][k],dp[i-1][(j-1)/2*2][(k-1)/2*2]+val);
                      if((j&1)==0 && dp[(i-1)/2*2][j-1][(k-1)/2*2]>=0)
                       dp[i][j][k]=max(dp[i][j][k],dp[(i-1)/2*2][j-1][(k-1)/2*2]+val);
                      if((k&1)==0 && dp[(i-1)/2*2][(j-1)/2*2][k-1]>=0)
                       dp[i][j][k]=max(dp[i][j][k],dp[(i-1)/2*2][(j-1)/2*2][k-1]+val);

                      if((j&1)==0 && (k&1)==0 && dp[(i-1)/2*2][j-1][k-1]>=0)
                       dp[i][j][k]=max(dp[i][j][k],dp[(i-1)/2*2][j-1][k-1]+val);
                      if((i&1)==0 && (k&1)==0 && dp[i-1][(j-1)/2*2][k-1]>=0)
                       dp[i][j][k]=max(dp[i][j][k],dp[i-1][(j-1)/2*2][k-1]+val);
                      if((i&1)==0 && (j&1)==0 && dp[i-1][j-1][(k-1)/2*2]>=0)
                       dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][(k-1)/2*2]+val);
              }
        ans=-1;
        for(i=0;i<=1;i++)
           for(j=0;j<=1;j++)
              for(k=0;k<=1;k++)
                 ans=max(ans,dp[len[1]*2+i][len[2]*2+j][len[3]*2+k]);
        printf("%d\n",ans);
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值