题解:P11876 收徒!
题目描述
给 定一个
思路分析
1.暴力思路
构建一个数组容器,每次弹出一个并压入向下和向右俩个方向。明显不行。
2.棋盘 dp 思路
思路类似于经典入门动态规划题目过河卒但是问题在于本题棋盘大小为
3.棋子 dp 思路
观察题目,我们发现棋子的数量为
重点:我们可以发现对于任意的棋子,他都是由他左上方的棋子或者是
举例:我们缩小棋子数量,有一个
因此,具体思路为开一个
时间复杂度最大为
4.棋子 dp 及二分思路(AC 思路)
我们发现对于每个棋子,若找了的可以从左上角来的棋子,若记从
代码如下
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
vector<int>m[N];
struct node{
int xx;
int yy;
}f[N];
bool cmp(node a,node b){
if(a.xx==b.xx){
return a.yy<b.yy;
}else{
return a.xx<b.xx;
}
}
int ly[N];
int main(){
int h,w,n;
cin>>h>>w>>n;
for(int i=1;i<=n;i++){
scanf("%d%d",&f[i].xx,&f[i].yy);
}
sort(f,f+n+1,cmp);//不能不要
int ma=0;
for(int i=1;i<=n;i++){
int l=1,r=ma;
int dqll=0;
int dq=0;
while(l<=r){
int mid=l+r>>1;
int flag=0;
int ll;
for(int k:m[mid]){
if(f[k].yy<=f[i].yy){
flag=1;
ll=k;
break;
}
}
if(flag){
if(mid>dq){
dq=mid;
dqll=ll;
}
l=mid+1;
}else{
r=mid-1;
}
}
ma=max(ma,dq+1);
ly[i]=dqll;
m[dq+1].push_back(i);
}
int ans=m[ma][0];
string s="";
int prow=ans;
int dqi=h;
int dqj=w;
while(1){
int proi=f[prow].xx;
int proj=f[prow].yy;
if(prow==0){
proi=1;
proj=1;
}
string dqs="";
for(int i=proi;i<dqi;i++){
dqs+='D';
}
for(int i=proj;i<dqj;i++){
dqs+='R';
}
s=dqs+s;
dqi=proi;
dqj=proj;
if(prow==0)break;
prow=ly[prow];
}
cout<<ma<<endl;
cout<<s<<endl;
}
/*
0 0 1 1 1
0 0 0 0 1
0 0 0 1 0
0 0 0 1 0
0 0 0 1 0
5 5 7
1 3
1 4
1 5
2 5
3 4
4 4
5 4
*/
蒟蒻第一次写题解,写的不好还请见谅,欢迎大家提问及纠错,最后求审核大大通过。