终于考完试了!!! 可以刷题了!!! >,<
题意:
图像识别 每个要识别的图像块可能缺一行像素或者多一行 要求整幅图像误差最小
思路:
DP题
预处理出g[i][j][k]表示第i行开始,匹配第j个图像快,匹配的第k行有多少误差
用g数组预处理出f[i][j][k]表示第i行开始,匹配第j个图像块,在缺一行、多一行、不多不少行的情况下的误差
通过f数组做DP dp[i]表示到i行位置最少误差 方程为 dp[i]=min( dp[from] + f[from][j][k] )
dp同时记录每个dp[i]更新过来的from和j(即保存答案所需要的dp路径)
代码:
/*
ID: housera1
PROG: charrec
LANG: C++
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 30
#define M 1210
#define bad 120
char maz[N][N][N],in[M][N],ans[M];
int f[M][N][3],g[M][N][N],dp[M],from[M],key[M];
int n;
int main()
{
int Debug=0;
int i,j,k,x,y,ff,tmp;
if(!Debug)
{
freopen("font.in","r",stdin);
freopen("charrec.out","w",stdout);
}
scanf("%d",&n);
for(i=0;i<=26;i++)
{
for(j=0;j<20;j++) scanf("%s",maz[i][j]);
}
if(!Debug) freopen("charrec.in","r",stdin);
scanf("%d",&n);
for(i=0;i<n;i++) scanf("%s",in[i]);
for(i=0;i<n;i++)
{
for(j=0;j<=26;j++)
{
for(k=0;k<20;k++)
{
tmp=0;
for(x=0;x<20;x++)
{
if(maz[j][k][x]!=in[i][x]) tmp++;
}
g[i][j][k]=tmp;
}
}
}
memset(f,-1,sizeof(f));
for(i=0;i<n;i++)
{
for(j=0;j<=26;j++)
{
if(i+19<n) //normal
{
tmp=0;
for(x=0;x<20;x++) tmp+=g[i+x][j][x];
if(tmp<=bad) f[i][j][1]=tmp;
}
if(i+20<n) //more
{
for(k=0;k<20;k++)
{
tmp=0;
for(x=0;x<20;x++)
{
ff=i+x;
if(x>k) ff++;
tmp+=g[ff][j][x];
}
if(tmp<=bad&&(f[i][j][2]==-1||tmp<f[i][j][2])) f[i][j][2]=tmp;
}
}
if(i+18<n) //less
{
for(k=0;k<20;k++)
{
tmp=0;
for(x=0;x<20;x++)
{
if(x==k) continue;
ff=i+x;
if(x>k) ff--;
tmp+=g[ff][j][x];
}
if(tmp<=bad&&(f[i][j][0]==-1||tmp<f[i][j][0])) f[i][j][0]=tmp;
}
}
}
f[i][27][0]=f[i][27][1]=f[i][27][2]=bad+10;
}
memset(dp,-1,sizeof(dp));
dp[0]=0;
for(i=0;i<n;i++)
{
if(dp[i]!=-1)
{
for(j=0;j<=27;j++)
{
for(k=0;k<=2;k++)
{
if(f[i][j][k]!=-1)
{
if(dp[i+k+19]==-1||dp[i+k+19]>dp[i]+f[i][j][k])
{
dp[i+k+19]=dp[i]+f[i][j][k];
from[i+k+19]=i;
key[i+k+19]=j;
}
}
}
}
}
}
for(i=n,j=0;i;i=from[i],j++)
{
if(!key[i]) ans[j]=' ';
else if(key[i]==27) ans[j]='?';
else ans[j]='a'+key[i]-1;
}
for(i=j-1;i>=0;i--) putchar(ans[i]);
puts("");
return 0;
}