把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P3685 [CERC2016]不可见的整数 Invisible Integers

题面传送门

真的吐了,写了五六个小时。

首先我们不考虑两边都能走,只考虑向左走,那么的话如果两个从左到右的集合分别为\(S1,S2\),则\(S1\subset S2\),且除去\(S1\)已经匹配掉的部分,剩下的点在\(S2\)中必定单调。这两个就是充要条件。

仿照这个,设\(dp_{S,p1,p2,l1,l2}\)表示已经不用考虑的点在\(S\)里面,向左的考虑到\(p1\)\(l1\)长度,向右的考虑到\(p2\)\(l2\)长度。然后复杂度大概就是\(O(n^3a^22^n)\)

但是实现起来细节一大堆。这里大概罗列几点。

向左走的要一开始就放进去,否则无法对接下来要放的向右走做出限制,向右走的则不能一开始就放进去。

到最后向左走的可以停止,这样会少掉对向右走的限制,可以再记录一下。

有些时候不一定能匹配就匹配更优,可以不匹配以减少限制。

还有自己犯的一个sb错误,循环顺序错乱。

反正就这些。

code:

#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=10+5,M=(1<<10)+5,K=2e3+5,mod=1e9+7,Mod=mod-1;const db eps=1e-5;const int INF=1e9+7;mt19937 rnd(time(0));
int n,m,k,x,y,z,A[N][N],T[N],g[N][N],dp[M][N][N][N][N],Ans=1e9,p[N][N],p1[N][N],p2[N][N],Ts[N];
void chkmin(int &x,int y){x>y&&(x=y);}
int main(){
	freopen("1.in","r",stdin);
	int i,j,h,x,y,k;scanf("%d",&n);for(i=1;i<=n;T[i]--,i++) while(scanf("%d",&A[i][++T[i]]),A[i][T[i]])Ts[i]|=(1<<A[i][T[i]]-1);
	for(i=1;i<=n;i++){
		for(j=1;j<=n;j++){x=T[j];for(h=T[i];h;h--){while(x&&A[j][x]^A[i][h]) x--;if(!x) {g[i][j]=h;break;}}p[i][j]=((Ts[i]&Ts[j])==Ts[i]);}
	}Me(dp,0x3f);for(i=1;i<=n;i++) dp[1<<i-1][i][0][T[i]][0]=0;
	for(i=0;i<(1<<n);i++)for(j=n;~j;j--)for(h=0;h<=n;h++)for(x=T[j];~x;x--)for(y=0;y<=T[h];y++){if(dp[i][j][h][x][y]>1e9) continue;
		if(x) {
			z=A[j][x];int Fl=0;for(k=1;k<=y+1;k++) if(A[h][k]==z){Fl=1;break;}
			if(Fl||!h){
				
				if(A[h][y+1]==z)chkin(dp[i][j][h][x-1][y+1],dp[i][j][h][x][y]+1); 
				else chkmin(dp[i][j][h][x-1][y],dp[i][j][h][x][y]+1);
			} 
		}
		if(y^T[h]){
			z=A[h][y+1];int Fl=0;for(k=1;k<=x;k++) if(A[j][k]==z) {Fl=1;break;}
			if(Fl||!j){
				if(A[j][x]==z) chkmin(dp[i][j][h][x-1][y+1],dp[i][j][h][x][y]+1);
				else 
				chkmin(dp[i][j][h][x][y+1],dp[i][j][h][x][y]+1);
			} 
		}
		if(!x&&j){
			for(k=1;k<=n;k++){if(i>>(k-1)&1||!p[j][k]) continue;
				for(int P=T[k];P>=g[k][j];P--) chkmin(dp[i|(1<<k-1)][k][h][P][y],dp[i][j][h][x][y]);
			}
			chkmin(dp[i][0][h][0][y],dp[i][j][h][x][y]);
		}
		if(!h) for(k=1;k<=n;k++) !(i>>(k-1)&1)&&(chkmin(dp[i|(1<<k-1)][j][k][x][0],dp[i][j][h][x][y]),0);
		else for(k=1;k<=n;k++) !(i>>(k-1)&1)&&g[h][k]<=y&&p[k][h]&&(chkmin(dp[i|(1<<k-1)][j][k][x][0],dp[i][j][h][x][y]),0);
	}
	for(i=0;i<=n;i++) for(j=0;j<=n;j++) chkmin(Ans,dp[(1<<n)-1][i][j][0][T[j]]);
	printf("%d\n",Ans>=1e9?-1:Ans); 
}
posted @ 2022-10-17 19:18  275307894a  阅读(83)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end