D. Minimum path
题意
给你一个字符矩阵,起点在左上角,每次可以向右或者向下走,可以改变这个字符矩阵中的k个字符,是这个路径构成的字符串字典序最小。
做法
由于可以改变k个字符,那么肯定是找到一条路径,前面至少有k项为a,
后面按照字典序选择路径就可以。
所以我们先用dp[i][j]表示从原点到(i,j)的路径中a最多有多少个。
之后对所有dp[i][j]-(i+j-1)>=k的点中选一个(i+j-1)最大的,
也就是能让前缀全是a的最长前缀,然后把所有满足的丢进vector
用滚动的vector每次选出往后走的字典序最小的,再丢尽vector
对每个点存一下他的上一个点,pre[i][j]
走到最后vector的大小为1,也就是走到终点,
最后通过pre[i][j]逆序输出答案
代码
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
const int maxn = 2005;
int n,k,dp[maxn][maxn];
int vis[maxn][maxn];
pii mp[maxn][maxn];
char pic[maxn][maxn];
vector<pii> ans[2];
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%s",pic[i]+1);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(pic[i][j]=='a')
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1])+1;
}
else
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
k=min(k,2*n-1);
int maxx=k;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dp[i][j]>=(i+j-1)-k) maxx=max(maxx,i+j-1);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dp[i][j]>=(i+j-1)-k&&(i+j-1)==maxx)
{
ans[0].push_back(pii(i,j));
}
}
}
string tmp="";
for(int i=1;i<=maxx;i++) tmp+='a';
int left;
if(tmp=="")
{
left=2*n-2;
ans[0].push_back(pii(1,1));
}
else
{
left=2*n-1-maxx;
}
for(int i=0;i<left;i++)
{
int minn=25;
for(int j=0;j<ans[i%2].size();j++)
{
int stx=ans[i%2][j].first;
int sty=ans[i%2][j].second;
if(stx<n) minn=min(minn,pic[stx+1][sty]-'a');
if(sty<n) minn=min(minn,pic[stx][sty+1]-'a');
}
ans[(i+1)%2].clear();
for(int j=0;j<ans[i%2].size();j++)
{
int stx=ans[i%2][j].first;
int sty=ans[i%2][j].second;
if(stx<n)
{
if(pic[stx+1][sty]-'a'==minn&&!vis[stx+1][sty])
{
vis[stx+1][sty]=1;
mp[stx+1][sty]=pii(stx,sty);
ans[(i+1)%2].push_back(pii(stx+1,sty));
}
}
if(sty<n)
{
if(pic[stx][sty+1]-'a'==minn&&!vis[stx][sty+1])
{
vis[stx][sty+1]=1;
mp[stx][sty+1]=pii(stx,sty);
ans[(i+1)%2].push_back(pii(stx,sty+1));
}
}
}
}
string ans="";
int sx=n,sy=n;
while(sx+sy-1>maxx)
{
ans+=pic[sx][sy];
pii tmp=mp[sx][sy];
sx=tmp.first;
sy=tmp.second;
}
reverse(ans.begin(),ans.end());
tmp+=ans;
printf("%s\n",tmp.c_str());
return 0;
}