codeforces 1072D Minimum path bfs+剪枝 好题

题目传送门

题目大意:

  给出一幅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=0,f=1;
    char ch=getchar();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 maxn=1e6+10;
struct node{
    int x,y,step;
    char pre;
    friend bool operator<(const node &a,const node &b)
    {
        return a.step<b.step;
    }
};
char ans[4010],mp[2010][2010];
int mk[2010][2010];
int pos,n,k;
queue<node>q[2];
int fx[2][2]={{0,1},{1,0}};
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>0){
    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=0;
    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-1]&&mk[s.x][s.y]==s.step){
        for(int i=0;i<2;i++){
            node ed=s;
            ed.x+=fx[i][0];
            ed.y+=fx[i][1];
            if(check(ed)){
                if(ed.step>mk[ed.x][ed.y]){
                mk[ed.x][ed.y]=ed.step;
                q[f^1].push(ed);
            }
            }
        }
    }

        if(q[f].empty()){
        f=f^1;
        pos++;
        ans[pos]=(char)(‘z‘+1);
        }
    }
}
int main(){
    cin>>n>>k;
    CLR(mk,-1);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",mp[i]+1);
    }
    if(mp[1][1]!=‘a‘&&k>0){
        k--;
        mp[1][1]=‘a‘;
    }
    ans[++pos]=mp[1][1];
    pos++;
    ans[pos]=‘z‘+1;
    mk[1][1]=k;
    q[0].push({1,1,k,ans[pos-1]});
    bfs();
    for(int i=1;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 2abcdbcdebcadbcde

output

Copy

aaabcde

input

Copy

5 3bwwwzhrhdhsepspsqfafajbvw

output

Copy

aaaepfafw

input

Copy

7 6ypnxnnppnxonpmnxanpouxnnpmudnhtdudunpmuduhpmutsnz

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.

原文地址:https://www.cnblogs.com/mountaink/p/9937616.html

时间: 2024-08-01 01:12:18

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

HDU 6223 Infinite Fraction Path(BFS+剪枝)

The ant Welly now dedicates himself to urban infrastructure. He came to the kingdom of numbers and solicited an audience with the king. He recounted how he had built a happy path in the kingdom of happiness. The king affirmed Welly's talent and hoped

POJ 3126 Prime Path (BFS+剪枝)

题目链接:传送门 题意: 给定两个四位数a,b,每次可以改变a的任意一位,并且确保改变后的a是一个素数. 问最少经过多少次改变a可以变成b. 分析: BFS,每次枚举改变的数,有一个剪枝,就是如果这个改变的数之前已经得到过了, 就没有必要继续变回它了. 代码如下: #include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <queue&g

Codeforces gym101755H Safe Path(bfs)

题意: 给以一个网格图,有起点终点和一些怪兽,可以上下左右走,不能走到距离怪兽曼哈顿距离为d以内的地方,问到终点最短路径 n*m<=2e5,d<=2e5 思路: 因为n*m的范围,不能直接建2e5*2e5的图,所以要vector.resize() 如果对每个怪兽都预处理的话,复杂度将是O(d2) 所以我们可以让所有怪兽同时走,这样预处理只有O(nm),也可以证明不会漏情况 代码: #include<iostream> #include<cstdio> #include&

leetcode_64题——Minimum Path Sum(动态规划)

Minimum Path Sum Total Accepted: 38669 Total Submissions: 120082My Submissions Question Solution Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Not

[LeetCode] Unique Paths &amp;&amp; Unique Paths II &amp;&amp; Minimum Path Sum (动态规划之 Matrix DP )

Unique Paths https://oj.leetcode.com/problems/unique-paths/ A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The robot can only move either down or right at any point in time. The robot is trying to rea

[leetcode]Minimum Path Sum @ Python

原题地址:https://oj.leetcode.com/problems/minimum-path-sum/ 题意: Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Note: You can only move either down or r

Poj1324(BFS+剪枝)

剪枝好题. 题目大意: 给一个地图,有一条蛇,给定从头到尾的各个点的坐标,地图上有些点是不能走的,然后就是跟以前玩过的贪吃蛇的规则一样了,蛇头不能碰到自己,问至少要多少步才能让蛇头从起点到达终点.地图长宽都是20以内,蛇长范围(2~8) 思路: 求最少步数,用bfs,图并不大,但是需要记录蛇的状态,还要判断重复.仔细观察,并不需要记录整个蛇各个点的坐标,也不需要把地图hash当做状态.我们要记录的状态无非就是蛇的位置. 那么其实也就是蛇头的坐标+蛇尾的相互关系.因为蛇是一个整体,身体的每一个部分

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

之所以将这三道题放在一起,是因为这三道题非常类似. 1. Minimum Path Sum 题目链接 题目要求: Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Note: You can only move either down or righ

LeetCode --- 64. Minimum Path Sum

题目链接:Minimum Path Sum Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Note: You can only move either down or right at any point in time. 这道题的要求是在m*n