传送门
http://codeforces.com/contest/1072/problem/D
重点!!!!
- i,j,k这些循环变量一定要分清楚
- scanf真的比cin快很多
思路
- 首先,预处理出用他给你的k个a,和序列里的a能走到哪,所及之处都替换成a
- 然后一边走,一边输出路径,如何??
- 用vis[i][j]表示在当前求出的最小字典序字符串,点(i,j)能不能走到
- 每次求出上次能走到的点能走到的点中字典序最小的
- 用这个去判断这次能走到的点中合法及不合法的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
inline int read(){
char ch=' ';int f=1;int x=0;
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=2010;
char s[N][N];
int f[N][N],vis[N][N];
int main()
{
int n,k;
n=read();k=read();
int i,j;
for(i=1;i<=n;i++)
{
scanf("%s",s[i]+1);
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(s[i][j]=='a') f[i][j]++;
if(i+j-1-f[i][j]<=k) s[i][j]='a';
}
}
cout<<s[1][1];vis[1][1]=1;
for(i=3;i<= n<<1 ;i++)
{
char mn='z'+1;
for(j=1;j<i;j++)
{
int k=i-j;
if(j>n||k>n) continue;
if(!vis[j-1][k]&&!vis[j][k-1]) continue;
if(s[j][k]<mn) mn=s[j][k];
}
cout<<mn;
for(j=1;j<i;j++)
{
int k=i-j;
if(j>n||k>n) continue;
if(!vis[j-1][k]&&!vis[j][k-1]) continue;
if(s[j][k]==mn) vis[j][k]=1;
}
}
return 0;
}