zoukankan      html  css  js  c++  java
  • 洛谷P3886 [JLOI2009]神秘的生物(插头dp)

    洛谷P3886 [JLOI2009]神秘的生物(插头dp)

    题目大意

    求带权正方形棋盘中最大权联通块

    数据范围

    [1 le n le 9 ]

    解题思路

    自己做出来的第一道插头 dp,不过很简单就是了

    由于这道题维护的是连通性,所以要用最小表示法记录一下每个点所在的联通块编号,然后就是轮廓线保留 n 个格子即可,因为插头处只用看看左边有没有块

    那么就分为两种情况了,一种是不放插头,一种是放一个插头

    不放插头要看看是不是会导致图不连通,放插头要将左和上的两个格子的联通块合并

    代码

    const int N = 5050;
    const int P = 3592;
    int h[N], ne[N], st[2][N], tot[2], val[2][N], nw, pr;
    void insert(int bit, int num) {
    //	printf ("%d %d
    ", bit, num);
    	int x = bit % P + 1;
    	for (int i = h[x]; i; i = ne[i]) 
    		if (st[nw][i] == bit) return Mx(val[nw][i], num);
    	ne[++tot[nw]] = h[x], st[nw][h[x] = tot[nw]] = bit, val[nw][tot[nw]] = num;
    }
    
    int vis[9], ans = -1e6, n;
    int reb(int bit) {
    	int now = 0, mx = 0;
    	memset(vis, 0, sizeof(vis));
    	for (int i = 0;i < n; i++) {
    		int p = bit >> (i * 3) & 7;
    		if (!p) continue;
    		if (!vis[p]) vis[p] = ++mx;
    		now |= vis[p] << (i * 3);
    	}
    	return now;
    }
    
    void update(int now, int val) {
    	for (int l = 0;l < n; l++)
    		if ((now >> (l * 3) & 7) > 1) return; 
    	Mx(ans, val);
    }
    
    int a[50][50];
    int main() {
    	read(n);
    	for (int i = 1;i <= n; i++)
    		for (int j = 1;j <= n; j++) 
    			read(a[i][j]), Mx(ans, a[i][j]);
    	if (ans <= 0) return write(ans), 0;
    	insert(0, 0); 
    	for (int i = 1;i <= n; i++) {
    		for (int j = 1;j <= n; j++) {
    			pr = nw, nw = nw ^ 1, tot[nw] = 0;
    			memset(h, 0, sizeof(h));
    			for (int k = 1;k <= tot[pr]; k++) {
    				int now = st[pr][k], V = val[pr][k];
    				int b1 = (j == 1) ? 0 : now >> ((j - 2) * 3) & 7; 
    				int b2 = now >> ((j - 1) * 3) & 7;
    				update(now, V);
    				int cc = 0;
    				for (int l = 0;l < n; l++) {
    					int pp = now >> (l * 3) & 7;
    					if (pp == b2) cc++;
    				}
    				if (cc > 1 || b2 == 0) insert(now ^ (b2 << ((j-1) * 3)), V);
    				for (int l = 0;l < n; l++) {
    					int pp = now >> (l * 3) & 7;
    					if (pp == 0) continue;
    					if (pp == b1 || pp == b2) 
    						now ^= (7 ^ pp) << (l * 3);
    				}
    				if (b2 == 0) now |= 7 << ((j-1) * 3);
    				insert(reb(now), V + a[i][j]);
    			}
    		}
    	}
    	for (int i = 1;i <= tot[nw]; i++)
    		update(st[nw][i], val[nw][i]);
    	write(ans);
    	return 0;
    }
    
  • 相关阅读:
    drf中 连表深度查询和ListSerializer类包括drf中Response二次封装
    drf中表之间断关联操作
    drf中的序列化家族
    rest_framework框架的封装特点和APIView请求生命周期
    vue项目和django项目交互补充,drf介绍,restful规范
    Vue成绩单
    面向对象编程day2
    面向对象编程day3
    面向对象编程day1
    day13
  • 原文地址:https://www.cnblogs.com/Hs-black/p/13353508.html
Copyright © 2011-2022 走看看