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> #includeView Code D. Minimum path time limit per test 1.5 seconds memory limit per test 256 megabytes input standard input output standard output<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 #defineCLR(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]); } }
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.
InputThe 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.
OutputOutput the lexicographically smallest string that can be associated with some valid path after changing no more than kk letters in the matrix.
Examples input Copy4 2output Copy
abcd
bcde
bcad
bcde
aaabcdeinput Copy
5 3output Copy
bwwwz
hrhdh
sepsp
sqfaf
ajbvw
aaaepfafwinput Copy
7 6output Copy
ypnxnnp
pnxonpm
nxanpou
xnnpmud
nhtdudu
npmuduh
pmutsnz
aaaaaaadudsnzNote
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+剪枝 好題