题目传送门

题目大意:

  给出一幅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. 189. Rotate Array 从右边开始翻转数组

    [抄题]: Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the ...

  2. Hyperledger Chaincode启动过程

    Chaincode 启动过程 简介 这里讲的 Chaincode 是用户链码(User Chaincode,UCC),对应用开发者来说十分重要,它提供了基于区块链分布式账本的状态处理逻辑,基于它可以开 ...

  3. osm2pgsql导入少字段

    Explanation: osm2pgsql imports normally the data in a static database schema. The tags without a cor ...

  4. MySQL中having与where

    having与where区别: where中不可以用聚合函数(条件字段是未分组中的字段),having中可以用聚合函(条件字段是分组后字段).不过这里也很好理解,SQL语句在执行是先执行select ...

  5. 认识HttpContext.User

    HttpContext.User,即IPrincipal .net源代码 namespace System.Security.Principal { /// <summary>Define ...

  6. UIPopoverController 简单用法(全代码)

     AppDelegate.m - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDic ...

  7. 开源IMS平台中间件Mobicents

    下面内容来自百度百科 Mobicents 是一个高伸缩性.事件驱动的应用服务器.是一款专业的.开放源代码的 VoIP 中间件平台.Mobicents是首个采用JAIN SLEE标准的开放式源代码电信应 ...

  8. RegExp正则表达式对象

    JavaScript的RegExp对象有两种创建方式,一种是字面量,一种是对象. var r = /pattern/attributes或者new RegExp(pattern, attributes ...

  9. android 透明弹出搜索框

    1.在QQ一些APP当中有是弹出一个半透明的搜索框的,其实这种效果就是很多种方法,自定义一个Dialog,或者直接将activity的背景变成半透明的也可以的. 下面就是将activity变成半透明的 ...

  10. python 面向对象十一 super函数

    python 面向对象十一 super函数   super函数用来解决钻石继承. 一.python的继承以及调用父类成员 父类: class Base(object): def __init__(se ...