题目传送门

题目大意:

  给出一幅n*n的字符,从1,1位置走到n,n,会得到一个字符串,你有k次机会改变某一个字符(变成a),求字典序最小的路径。

题解:

  (先吐槽一句,cf 标签是dfs题????)

  这道题又学到了,首先会发现,从原点出发,走x步,所有的情况都是在一条斜线上的,而再走一步就是下一条斜线。所以用两个队列进行bfs(把当前步和下一步要处理的字符分开)。

  到了这里思路就明朗了,每次走的时候如果本身的map里是a就直接走,不是a就看k是否大于0,再看这个字符是不是比答案串里对应位置的字符小,这样bfs主体就搭建完成了。

  但是优秀的bfs显然要考剪枝(Orz)。

  首先是一个保证正确性的剪枝,由于我们会更新某一个位子的字符,(c -> b -> a),但是修改的过程中前面那些并不是最优状态也被更新了,会导致答案错误,所以我采取的方法是记录每一个状态的字符,和答案串比较,是否一样,如果不一样,则代表答案串不是由这个状态变来的,continue掉。

  其次是一个会影响时间的剪枝,由于到一个位子的k有很多种情况,显然我们应该保存k最大的那种情况,而k比较小的那些情况其实是冗余的,严重超时,所以我们每次更新答案串的时候,还应该更新一下 保证答案最优的情况下走到每个位子最大的k是多少。当某一个状态front出来的时候,先比较是否k是最大(最优)的,如果不是,也continue。

  不过还有一个剪枝,应该是k>=2*n-1就可以直接输出aaaaa了,但是看时间似乎没必要。两个优先队列就用 f^1的方法就可以变化了。

//#pragma comment(linker,"/STACK:102400000,102400000")
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<stdlib.h>
//#include<unordered_map>
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)|1
#define CLR(a,b) memset(a,b,sizeof(a))
#define mkp(a,b) make_pair(a,b)
typedef long long ll;
using namespace std;
inline int read(){
int x=,f=;
char ch=getchar();while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;}
const int maxn=1e6+;
struct node{
int x,y,step;
char pre;
friend bool operator<(const node &a,const node &b)
{
return a.step<b.step;
}
};
char ans[],mp[][];
int mk[][];
int pos,n,k;
queue<node>q[];
int fx[][]={{,},{,}};
inline bool check(node &s)
{
if(s.x>n||s.y>n)return false;
if(mp[s.x][s.y]=='a'){
ans[pos]='a';
s.pre='a';
return true;
}
if(s.step>){
s.pre='a';
ans[pos]='a';
//printf("ans[%d]:%c\n",pos,ans[pos]);
s.step--;
return true;
}
if(ans[pos]>=mp[s.x][s.y]){
ans[pos]=mp[s.x][s.y];
s.pre=ans[pos];
return true;
}
return false;
}
inline void bfs()
{
int f=;
while(!q[f].empty())
{
node s=q[f].front();
q[f].pop(); if(s.x==s.y&&s.x==n)continue;
if(s.pre==ans[pos-]&&mk[s.x][s.y]==s.step){
for(int i=;i<;i++){
node ed=s;
ed.x+=fx[i][];
ed.y+=fx[i][];
if(check(ed)){
if(ed.step>mk[ed.x][ed.y]){
mk[ed.x][ed.y]=ed.step;
q[f^].push(ed);
}
}
}
} if(q[f].empty()){
f=f^;
pos++;
ans[pos]=(char)('z'+);
}
}
}
int main(){
cin>>n>>k;
CLR(mk,-);
for(int i=;i<=n;i++)
{
scanf("%s",mp[i]+);
}
if(mp[][]!='a'&&k>){
k--;
mp[][]='a';
}
ans[++pos]=mp[][];
pos++;
ans[pos]='z'+;
mk[][]=k;
q[].push({,,k,ans[pos-]});
bfs();
for(int i=;i<pos;i++)
{
printf("%c",ans[i]);
}
}
D. Minimum path
time limit per test

1.5 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a matrix of size n×nn×n filled with lowercase English letters. You can change no more than kk letters in this matrix.

Consider all paths from the upper left corner to the lower right corner that move from a cell to its neighboring cell to the right or down. Each path is associated with the string that is formed by all the letters in the cells the path visits. Thus, the length of each string is 2n−12n−1.

Find the lexicographically smallest string that can be associated with a path after changing letters in at most kk cells of the matrix.

A string aa is lexicographically smaller than a string bb, if the first different letter in aa and bb is smaller in aa.

Input

The first line contains two integers nn and kk (1≤n≤20001≤n≤2000, 0≤k≤n20≤k≤n2) — the size of the matrix and the number of letters you can change.

Each of the next nn lines contains a string of nn lowercase English letters denoting one row of the matrix.

Output

Output the lexicographically smallest string that can be associated with some valid path after changing no more than kk letters in the matrix.

Examples
input

Copy
4 2
abcd
bcde
bcad
bcde
output

Copy
aaabcde
input

Copy
5 3
bwwwz
hrhdh
sepsp
sqfaf
ajbvw
output

Copy
aaaepfafw
input

Copy
7 6
ypnxnnp
pnxonpm
nxanpou
xnnpmud
nhtdudu
npmuduh
pmutsnz
output

Copy
aaaaaaadudsnz
Note

In the first sample test case it is possible to change letters 'b' in cells (2,1)(2,1) and (3,1)(3,1) to 'a', then the minimum path contains cells (1,1),(2,1),(3,1),(4,1),(4,2),(4,3),(4,4)(1,1),(2,1),(3,1),(4,1),(4,2),(4,3),(4,4). The first coordinate corresponds to the row and the second coordinate corresponds to the column.

codeforces 1072D Minimum path bfs+剪枝 好题的更多相关文章

  1. HDU6223 Infinite Fraction Path bfs+剪枝

    Infinite Fraction Path 这个题第一次看见的时候,题意没搞懂就没做,这第二次也不会呀.. 题意:第i个城市到第(i*i+1)%n个城市,每个城市有个权值,从一个城市出发走N个城市, ...

  2. 2017沈阳区域赛Infinite Fraction Path(BFS + 剪枝)

    Infinite Fraction Path Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java ...

  3. Vladik and Favorite Game CodeForces - 811D (思维+BFS+模拟+交互题)

    D. Vladik and Favorite Game time limit per test 2 seconds memory limit per test 256 megabytes input ...

  4. POJ 3126 Prime Path (BFS+剪枝)

    题目链接:传送门 题意: 给定两个四位数a.b,每次能够改变a的随意一位.而且确保改变后的a是一个素数. 问最少经过多少次改变a能够变成b. 分析: BFS,每次枚举改变的数,有一个剪枝,就是假设这个 ...

  5. cf1072D. Minimum path(BFS)

    题意 题目链接 给出一个\(n \times n\)的矩阵,允许修改\(k\)次,求一条从\((1, 1)\)到\((n, n)\)的路径.要求字典序最小 Sol 很显然的一个思路是对于每个点,预处理 ...

  6. Codeforces gym101755H Safe Path(bfs)

    题意: 给以一个网格图,有起点终点和一些怪兽,可以上下左右走,不能走到距离怪兽曼哈顿距离为d以内的地方,问到终点最短路径 n*m<=2e5,d<=2e5 思路: 因为n*m的范围,不能直接 ...

  7. 刷题64. Minimum Path Sum

    一.题目说明 题目64. Minimum Path Sum,给一个m*n矩阵,每个元素的值非负,计算从左上角到右下角的最小路径和.难度是Medium! 二.我的解答 乍一看,这个是计算最短路径的,迪杰 ...

  8. 动态规划小结 - 二维动态规划 - 时间复杂度 O(n*n)的棋盘型,题 [LeetCode] Minimum Path Sum,Unique Paths II,Edit Distance

    引言 二维动态规划中最常见的是棋盘型二维动态规划. 即 func(i, j) 往往只和 func(i-1, j-1), func(i-1, j) 以及 func(i, j-1) 有关 这种情况下,时间 ...

  9. LeetCode之“动态规划”:Minimum Path Sum && Unique Paths && Unique Paths II

    之所以将这三道题放在一起,是因为这三道题非常类似. 1. Minimum Path Sum 题目链接 题目要求: Given a m x n grid filled with non-negative ...

随机推荐

  1. 多个if和一个ifelse的区别

    一个程序的要求如下,输入一个学生的数学成绩,如果大于等于60,那么就输出good,如果小于60那么输出not good int a scanf_s("%d",&a) if( ...

  2. Linux 与 BSD

    1)Linux 与 BSD 有什么不同? http://linux.cn/article-3186-1.html 2)BSD(Unix)家族 http://blog.csdn.net/cradmin/ ...

  3. bootstrap图片切换效果

    <!DOCTYPE html><html lang="zh-cn"><head><meta charset="utf-8&quo ...

  4. centos7 安装pip

    首先安装 python3 安装过程1.安装相关依赖 1 sudo yum install openssl-devel -y 2 sudo yum install zlib-devel -y 2.安装s ...

  5. C#中如何向数组中动态添加元素

    转自:https://blog.csdn.net/qq_35938548/article/details/78325558 背景:现需要向数组中循环插入字符串,但C#中的数组是不支持动态添加元素的,只 ...

  6. go的Type switch是一个switch语句么?

    相信这样的语句在go中大家见的很多 switch t := arg.(type) { default: fmt.Printf("unexpected type %T\n", t) ...

  7. 微信H5或PC支付常见问题汇总

    1.H5端调起支付,直接提示[支付失败],打印具体的信息,“<当前URL不存在>” 原因: ①.[支付授权目录不对]---查看微信商户平台的支付授权目录的地址,如果MVC结构的,则只需填写 ...

  8. Launch VINS-Mono with Realsense D435i in RTAB-Map

    Preparation: Remap topic from D435i to rtabmap Feed the odometry to rtabmap In the rqt_graph of vins ...

  9. luoguP3302 [SDOI2013]森林

    https://www.luogu.org/problemnew/show/P3302 看到查询第 k 小,而且是一颗树,可以联想到在树上的主席树,a 和 b 路径中第 k 小可以通过在 a, b, ...

  10. 洛谷P2764 最小路径覆盖问题(最大流)

    传送门 先说做法:把原图拆成一个二分图,每一个点被拆成$A_i,B_i$,若原图中存在边$(u,v)$,则连边$(A_u,B_v)$,然后$S$对所有$A$连边,所有$B$对$T$连边,然后跑一个最大 ...