【JZOJ5738】【20190706】锁屏杀

题目

img

img

img

$n \le 2000 $

题解

  • \(B\)的数字可以对1440取模,对三个图分别进行\(dp\)即可
  • 时间复杂度\(O(n\times 1440 \times 10)\)

Code

#include<bits/stdc++.h>
#define il inline 
using namespace std;
const int N=2100,P=1440;
int n,cnt[128],F[P],G1[P],G2[P],mp[N],a[N][10];
char S[7][N];
int num[10][5]={
	{127,65,65,127,0},
	{0,0,0,127,0},
	{121,73,73,79,0},
	{73,73,73,127,0},
	{15,8,8,127,0},
	{79,73,73,121,0},
	{127,73,73,121,0},
	{1,1,1,127,0},
	{127,73,73,127,0},
	{79,73,73,127,0}
};
il void upd(int&x,int y){if(x>y)x=y;}
il int get(int x,int y){
	int re=0;
	for(int i=0;i<5;++i)re+=cnt[mp[x+i]^num[y][i]];
	return re;
}
void init(){
	scanf("%d",&n);
	for(int i=6;~i;--i)scanf("%s",S[i]+1);
	
	for(int i=1,x;i<=n;mp[i++]=x)
	for(int j=x=0;j<7;++j)
		x=x<<1|(S[j][i]=='X');
	mp[n+1]=0;

	memset(a,1,sizeof(a));
	for(int i=1;i<=n-3;++i)
	for(int j=0;j<10;++j)
		a[i][j]=get(i,j);
}
void solve2(int *re){
	static int f[N][P],g[N],s[N];
	memset(f,1,sizeof(f));
	memset(g,1,sizeof(g));
	memset(s,1,sizeof(s));
	init();
	
	s[0]=0;
	for(int i=0;i<=n;++i){
		int t=cnt[mp[i+1]];
		s[i+1]=s[i]+t;
		
		upd(g[i+1],g[i]+t);
		upd(g[i+5],s[i]+a[i+1][0]);
		for(int j=1;j<10;++j){
			upd(f[i+5][j],s[i]+a[i+1][j]);
		}	
		for(int j=0;j<P;++j){
			upd(f[i+1][j],f[i][j]+t);
			for(int k=0;k<10;++k){
				upd(f[i+5][(j*10+k)%P],f[i][j]+a[i+1][k]);
			}
		}

	}
	
	for(int i=1;i<P;++i)re[i]=f[n+1][i];
	re[0]=min(g[n+1],f[n+1][0]);
}
void solve1(int *re){
	static int l[N][3],L[N][24],r[N][10],R[N][60],s[N];
	init();
	memset(l,1,sizeof(l));
	memset(r,1,sizeof(r));
	memset(L,1,sizeof(L));
	memset(R,1,sizeof(R));
	memset(s,1,sizeof(s));
		
	s[0]=0;
	for(int i=0;i<=n;++i){
		int t=cnt[mp[i+1]];
		s[i+1]=s[i]+t;
		for(int j=0;j<3;++j){
			upd(l[i+1][j],l[i][j]+t);
			upd(l[i+5][j],s[i]+a[i+1][j]);
		}
		for(int j=0;j<10;++j){
			upd(L[i+1][j],L[i][j]+t);
			upd(L[i+1][10+j],L[i][10+j]+t);
			upd(L[i+5][j],l[i][0]+a[i+1][j]);
			upd(L[i+5][10+j],l[i][1]+a[i+1][j]);
		}
		for(int j=0;j<4;++j){
			upd(L[i+1][20+j],L[i][20+j]+t);
			upd(L[i+5][20+j],l[i][2]+a[i+1][j]);
		}
	}
	
	s[n+1]=s[n+2]=0;
	for(int i=n;i;--i){
		int t=cnt[mp[i]];
		s[i]=s[i+1]+t;
		for(int j=0;j<10;++j){
			upd(r[i][j],r[i+1][j]+t);
			upd(r[i][j],a[i][j]+s[i+5]);
		}
		for(int j=0;j<6;++j)
		for(int k=0;k<10;++k){
			int x=10*j+k;
			upd(R[i][x],R[i+1][x]+t);
			upd(R[i][x],a[i][j]+r[i+5][k]);
		}
	}

	for(int i=0;i<24;++i)
	for(int j=0;j<60;++j){
		int t=0x3f3f3f3f;
		for(int k=1;k<=n+1;++k)
			upd(t,L[k-1][i]+R[k+2][j]+cnt[mp[k]^20]+cnt[mp[k+1]]);
		re[i*60+j]=t;
	}
}
void getans(){
	int re=0x3f3f3f3f;
	for(int i=0;i<P;++i)
	for(int j=0;j<P;++j){
		int t=j-i;if(t<0)t+=P;
		upd(re,G1[i]+G2[j]+F[t]);
	}
	cout<<re<<endl;
}
int main(){
	freopen("joke.in","r",stdin);
	freopen("joke.out","w",stdout);
	for(int i=1;i<128;++i)cnt[i]=cnt[i>>1]+(i&1);
	solve1(G1);
	solve2(F);
	solve1(G2);
	getans();
	return 0;
}
posted @ 2019-07-07 16:31  大米饼  阅读(314)  评论(0编辑  收藏  举报