USACO5.4-Character Recognition


题目大意是字符串识别
一道细节很繁琐的DP,要用到很多数组
一开始还真看不出是DP,后来参考了别人的代码,然后又按自己的思路重头到尾写了,虽然速度不咋的

Executing...
Test 1: TEST OK [0.008 secs, 6504 KB]
Test 2: TEST OK [0.008 secs, 6504 KB]
Test 3: TEST OK [0.019 secs, 6504 KB]
Test 4: TEST OK [0.035 secs, 6504 KB]
Test 5: TEST OK [0.084 secs, 6504 KB]
Test 6: TEST OK [0.116 secs, 6504 KB]
Test 7: TEST OK [0.167 secs, 6504 KB]
Test 8: TEST OK [0.192 secs, 6504 KB]
Test 9: TEST OK [0.178 secs, 6504 KB]

All tests OK.
YOUR PROGRAM ('charrec') WORKED FIRST TIME! That's fantastic
-- and a rare thing. Please accept these special automated
congratulations.

  1 #include <stack>
  2 #include <iostream>
  3 #include <stdio.h>
  4 #define R19 0
  5 #define R20 1
  6 #define R21 2
  7 #define INF 1000000000
  8 using namespace std;
  9 
 10 char ch[28][22][22];
 11 char mat[1210][22];
 12 int dif[28][22][1210];
 13 int cost[1210][4]; // cost[i][j]表示从mat的第i行开始匹配j行得到的最小差距
 14 int optimalCh[1210][4]; // optimalCh[i][j]表示从mat的第i行开始匹配j行最优的匹配字符
 15 int d[1210]={0}; // d[i]表示匹配到第i行所得到的最小差距
 16 int step[1210]; // step[i]表示第i行开始的最优匹配的字符行数
 17 // 得到行数中不同的个数
 18 /*
 19 num为第几个字符
 20 l1为num字符的行数
 21 l2为mat的行数
 22 */
 23 int getDif(int num,int l1,int l2)
 24 {
 25     int sum=0;
 26     for(int i=0;i<20;i++)
 27     {
 28         if(ch[num][l1][i]!=mat[l2][i])
 29             sum++;
 30     }
 31     return sum;
 32 }
 33 
 34 // num为字符,l1为mat开始匹配的行数,del为删除了哪一行
 35 int getCost(int num,int l1,int del)
 36 {
 37     int sum=0;
 38     for(int i=0,p=0;p<19;i++,p++)
 39     {
 40         if(i==del)
 41             i++;
 42         sum+=dif[num][i][l1+p];
 43     }
 44     return sum;
 45 }
 46 
 47 int getCost2(int num,int l1,int del)
 48 {
 49     int sum=0;
 50     for(int i=0,p=0;i<20;i++,p++)
 51     {
 52         if(p==del)
 53             p++;
 54         sum+=dif[num][i][p+l1];
 55     }
 56     return sum;
 57 }
 58 
 59 
 60 int main()
 61 {
 62     freopen("font.in","r",stdin);
 63     int n; // 行数
 64     cin>>n;
 65     for(int i=0;i<n/20;i++)
 66     {
 67         for(int j=0;j<20;j++)
 68         {
 69             scanf("%s",ch[i][j]);
 70 
 71         }
 72     }
 73 
 74     freopen("charrec.in","r",stdin);
 75     freopen("charrec.out","w",stdout);
 76 
 77     cin>>n;
 78 
 79     for(int i=0;i<n;i++)
 80         scanf("%s",mat[i]);
 81 
 82     // 初始化dif数组
 83     for(int i=0;i<27;i++)
 84         for(int j=0;j<20;j++)
 85         {
 86             for(int k=0;k<n;k++)
 87             {
 88                 dif[i][j][k]=getDif(i,j,k);
 89             }
 90         }
 91 
 92     // 初始化cost
 93     for(int i=0;i<n;i++) // 从第i行开始匹配
 94     {
 95         cost[i][R19]=cost[i][R20]=cost[i][R21]=INF;
 96         for(int j=0;j<27;j++) // 第j个字符
 97         {
 98             if(i+19<n+1)
 99             {
100                 for(int k=0;k<20;k++) // 删掉行数
101                 {
102                     if(cost[i][R19]>getCost(j,i,k))
103                     {
104                         cost[i][R19]=getCost(j,i,k);
105                         optimalCh[i][R19]=j;
106                     }
107                 }
108             }
109             if(i+20<n+1)
110             {
111                 if(cost[i][R20]>getCost(j,i,-1))
112                 {
113                     cost[i][R20]=getCost(j,i,-1);
114                     optimalCh[i][R20]=j;
115                 }
116             }
117             if(i+21<n+1)
118             {
119                 for(int k=0;k<21;k++) // 多出的行数
120                 {
121                     if(cost[i][R21]>getCost2(j,i,k))
122                     {
123                         cost[i][R21]=getCost2(j,i,k);
124                         optimalCh[i][R21]=j;
125                     }
126                 }
127             }
128         }
129     }
130 
131     fill_n(d,n+5,INF);
132     // 初始值
133     d[18]=cost[0][R19];step[18]=19;
134     d[19]=cost[0][R20];step[19]=20;
135     d[20]=cost[0][R21];step[20]=21;
136     // DP
137     for(int i=21;i<n;i++) // 匹配的最后一行为i
138     {
139         if(d[i-19]+cost[i-18][R19]<d[i])
140         {
141             d[i]=d[i-19]+cost[i-18][R19];
142             step[i]=19;
143         }
144         if(d[i-20]+cost[i-19][R20]<d[i])
145         {
146             d[i]=d[i-20]+cost[i-19][R20];
147             step[i]=20;
148         }
149         if(d[i-21]+cost[i-20][R21]<d[i])
150         {
151             d[i]=d[i-21]+cost[i-20][R21];
152             step[i]=21;
153         }
154     }
155 
156     stack<int> S;
157 
158     for(int p=n-1;p!=-1;p=p-step[p])
159     {
160         S.push(optimalCh[p-step[p]+1][step[p]-19]);
161     }
162 
163     while(!S.empty())
164     {
165         int tmp=S.top();
166         S.pop();
167         printf("%c",tmp==0?' ':tmp-1+'a');
168     }
169     cout<<endl;
170     return 0;
171 }
原文地址:https://www.cnblogs.com/oneshot/p/3979715.html