可能是我傻
假如没有三点变四点的操作,这就是一道入门的二维dp。
一开始一直想着怎么把三点变四点的表弄出来,结果gg
正解考虑结合二分图,对于已经存在的“雷神轴标” xi , yi,在二分图中从 xi 向 yi 连边。
然后,对于一个坐标 x , y,只要在二分图中 x , y在同一连通块中,则一定会产生“雷神轴标” x , y。并查集实现。
结合这点,二维dp即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 6 const int maxsize=5005; 7 8 int n,maxx,maxy; 9 int par[maxsize<<1],f[maxsize][maxsize]; 10 11 int find(int x){ return par[x]==x?x:par[x]=find(par[x]); } 12 13 void unite(int x,int y){ 14 int f1=find(x),f2=find(y); 15 if(f1==f2) return; 16 par[f2]=f1; 17 } 18 19 void init(){ 20 for(int i=1;i<=10005;i++) par[i]=i; 21 scanf("%d",&n); 22 for(int i=1,x,y;i<=n;i++){ 23 scanf("%d%d",&x,&y); 24 maxx=max(maxx,x); 25 maxy=max(maxy,y); 26 unite(x,y+5000); 27 } 28 } 29 30 void solve(){ 31 for(int i=1;i<=maxx;i++) 32 for(int j=1;j<=maxy;j++) 33 if(find(i)==find(j+5000)) f[i][j]=max(f[i-1][j],f[i][j-1])+1; 34 else f[i][j]=max(f[i-1][j],f[i][j-1]); 35 printf("%d ",f[maxx][maxy]); 36 } 37 38 int main(){ 39 //freopen("field.in","r",stdin); 40 //freopen("field.out","w",stdout); 41 init(); 42 solve(); 43 return 0; 44 }