1. 程式人生 > >codeforces 1072D Minimum path bfs+剪枝 好題

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]); } }
View Code 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 2n12n−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 (1n20001≤n≤2000, 0kn20≤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.