题目大意:
给出一幅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