USACO 5.4.2 以后在理解

   这道题的意思是到现在理解的不太透彻, 以后需要在看,  先把代码贴上吧

/*
    ID: m1500293
    LANG: C++
    PROG: charrec
*/
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const char letter[30] = " abcdefghijklmnopqrstuvwxyz";
int ans[1201];
int font[28][21][21];
int data[1201][21], dif[28][21][1201];    //dif表示第i个字符的第j行和输入的第k行的差距
int cost[1201][4];  //表示从第i行开始
int from[1201][4];
int f[1201], g[1201];
int main()
{
    freopen("font.in", "r", stdin);
    int n;
    scanf("%d", &n);  getchar();
    for(int i=1; i<=27; i++)
        for(int j=1; j<=20; j++)
        {
            for(int k=1; k<=20; k++)
                font[i][j][k] = getchar();
            getchar();
        }
    freopen("charrec.in", "r", stdin);
    freopen("charrec.out", "w", stdout);
    scanf("%d", &n); getchar();
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=20; j++)
            data[i][j] = getchar();
        getchar();
    }
    //预处理dif数组
    for(int i=1; i<=27; i++)
        for(int j=1; j<=20; j++)
        for(int k=1; k<=n; k++)
        for(int p=1; p<=20; p++)
        if(data[k][p] != font[i][j][p])
        dif[i][j][k]++;
    //预处理cost数组
    for(int i=1; i<=n; i++)
    {
        cost[i][1] = cost[i][2] = cost[i][3]=0x3fffffff;
        if(i+18 <= n)    //缺失一行
        for(int j=1; j<=27; j++)
        {
            int total=0;
            for(int k=2; k<=20; k++)  total += dif[j][k][i+k-2];
            if(total < cost[i][1]) cost[i][1]=total, from[i][1]=j;
            for(int k=2; k<=20; k++)
            {
                total += dif[j][k-1][i+k-2]; total -= dif[j][k][i+k-2];
                if(total<cost[i][1]) cost[i][1]=total, from[i][1]=j;
            }
        }
        if(i+19 <= n)   //正好20行
        for(int j=1; j<=27; j++)
        {
            int total = 0;
            for(int k=1; k<=20; k++) total += dif[j][k][i+k-1];
            if(total < cost[i][2]) cost[i][2]=total, from[i][2]=j;
        }
        if(i+20<=n)    //多一行
        for(int j=1; j<=27; j++)
        {
            int total = dif[j][1][i];
            for(int k=2; k<=20; k++) total += dif[j][k][i+k];
            if(total<cost[i][3]) cost[i][3]=total, from[i][3]=j;
            for(int k=2; k<=20; k++)    //多第k行
            {
                total += dif[j][k][i+k-1]; total -= dif[j][k][i+k];
                if(total < cost[i][3]) cost[i][3] = total, from[i][3] = j;
            }
        }
    }
    int inf = 0x3fffffff;
    f[0] = 0;
    for(int i=1; i<=n; i++) f[i] = inf;
    for(int i=19; i<=n; i++)
    {
        if(i>=19 && f[i-19]<inf && f[i-19]+cost[i-18][1]<f[i])
            f[i]=f[i-19]+cost[i-18][1], g[i]=19;
        if(i>=20 && f[i-20]<inf && f[i-20]+cost[i-19][2]<f[i])
            f[i]=f[i-20]+cost[i-19][2], g[i]=20;
        if(i>=21 && f[i-21]<inf && f[i-21]+cost[i-20][3]<f[i])
            f[i]=f[i-21]+cost[i-20][3], g[i]=21;
    }
    int total = 0;
    for(int i=n; i; i-=g[i])
        ans[++total] = from[i-g[i]+1][g[i]-18];
    for(int i=total; i; i--) printf("%c", letter[ans[i]-1]);
    printf("\n");
    return 0;
}

 

你可能感兴趣的:(USACO 5.4.2 以后在理解)