• [BZOJ1659][Usaco2006 Mar]Lights Out 关灯


    [BZOJ1659][Usaco2006 Mar]Lights Out 关灯

    试题描述

    奶牛们喜欢在黑暗中睡觉。每天晚上,他们的牲口棚有L(3<=L<=50)盏灯,他们想让亮着的灯尽可能的少。他们知道按钮开关的位置,但喜闻乐见的是他们并没有手指。你得到了一个长度为T(1<=T<=7)的插槽用以帮助奶牛们改变灯的状态。

    输入

    第一行,两个整数L和T。第二行给出一个长度为L的01串表示初始灯的状态,0表示灯是灭的,1表示灯是亮的。第三行给出一个长度为T的01串,表示你获得的插槽。

    输出

    第一行输出一个整数K,表示在满足亮着的灯最少的情况下,你要用插槽操作的次数。第二行到第K+1行,每行一个整数表示你的插槽使用的位置。
    "K最小的解,并且满足解的字典序最大(即按钮开关的位置尽可能靠后)"

    输入示例

    10 4
    1111111111
    1101

    输出示例

    5
    1
    3
    4
    6
    7

    数据规模及约定

    见“试题描述

    题解

    暴力大 dp,设 f(i, S) 表示考虑是否在第 i 个位置使用插槽,分为两个转移。根据当前的 S 推第 i-1 个位置的状态,更新当前的答案。

    再记一下方案,使其步数最小且字典序最大。

    然后使劲写就行了,范围小随便写。

    下面是代码,估计没人想看。。。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 55
    #define maxm 10
    #define maxst 130
    #define oo 147483647
    #define LL long long
    int n, m, Lig[maxn], Swi[maxm], f[maxn][maxst], g[maxn][maxst][maxn], cg[maxn][maxst];
    
    int bin[maxm], cb;
    void Bin(int s) {
    	cb = 0;
    	while(s) {
    		bin[++cb] = (s & 1);
    		s >>= 1;
    	}
    	for(int i = cb; i; i--) printf("%d", bin[i]);
    	if(!cb) putchar('0');
    	return ;
    }
    
    int _s, _l;
    LL ls[maxn];
    int lit(int a, int b) { return ls[b] - (ls[a-1] << b-a+1); }
    int cntl(int t, int n) {
    	int ans = 0;
    	for(int i = 1; i <= n; i++) {
    		if(!(t & 1)) ans++;
    		t >>= 1;
    	}
    	return ans;
    }
    bool larger(int i, int j, int a, int b) {
    	if(cg[i][j] != cg[a][b]) return cg[i][j] < cg[a][b];
    	int c = cg[i][j];
    	for(int k = 1; k <= c; k++) if(g[i][j][k] != g[a][b][k]) return g[i][j][k] > g[a][b][k];
    	return 0;
    }
    
    int main() {
    	read(); read();
    	char tc = Getchar();
    	while(!isdigit(tc)) tc = Getchar();
    	while(isdigit(tc)) {
    		Lig[++n] = tc - '0';
    		tc = Getchar();
    	}
    	while(!isdigit(tc)) tc = Getchar();
    	int cnt = 0, _c = 0;
    	while(isdigit(tc)) {
    		Swi[++m] = tc - '0';
    		_s = _s << 1 | Swi[m];
    		_l = _l << 1 | Lig[m];
    		cnt += (Lig[m] ^ 1);
    		_c += (Lig[m] ^ Swi[m] ^ 1);
    		tc = Getchar();
    	}
    	
    	int all = (1 << m) - 1;
    	for(int S = 0; S <= all; S++) f[1][S] = -oo;
    	f[1][_l] = cnt;
    	f[1][_l^_s] = _c; cg[1][_l^_s] = 1; g[1][_l^_s][1] = 1;
    	for(int i = 1; i <= n; i++) ls[i] = ls[i-1] << 1 | Lig[i];
    	for(int i = 2; i <= n - m + 1; i++)
    		for(int S = 0; S <= all; S++) {
    			f[i][S] = -oo;
    			for(int t = 0; t <= 1; t++) {
    				int SS = (t << m-1) | (S >> 1);
    //				printf("%d ", i-1); Bin(SS); putchar(' '); printf("%d	", f[i-1][SS]);
    				if((S & 1) == Lig[i+m-1]) {
    					int tmp = f[i-1][SS] + (Lig[i+m-1] ^ 1);
    					if(tmp > f[i][S]) {
    						f[i][S] = tmp;
    						cg[i][S] = cg[i-1][SS];
    						for(int k = 1; k <= cg[i][S]; k++) g[i][S][k] = g[i-1][SS][k];
    					}
    					else if(tmp == f[i][S] && larger(i-1, SS, i, S)) {
    						cg[i][S] = cg[i-1][SS];
    						for(int k = 1; k <= cg[i][S]; k++) g[i][S][k] = g[i-1][SS][k];
    					}
    				}
    				SS = (t << m-1) | ((S ^ _s) >> 1);
    //				printf("%d ", i-1); Bin(SS); putchar(' '); printf("%d	", f[i-1][SS]);
    				if((S & 1) == (Lig[i+m-1] ^ Swi[m])) {
    					int tmp = f[i-1][SS] - cntl((S ^ _s) >> 1, m-1) + cntl(S, m);
    					if(tmp > f[i][S]) {
    						f[i][S] = tmp;
    						cg[i][S] = cg[i-1][SS];
    						for(int k = 1; k <= cg[i][S]; k++) g[i][S][k] = g[i-1][SS][k];
    						g[i][S][++cg[i][S]] = i;
    					}
    					else if(tmp == f[i][S]) {
    						g[i-1][SS][++cg[i-1][SS]] = i;
    						if(larger(i-1, SS, i, S)) {
    							cg[i][S] = cg[i-1][SS]; cg[i-1][SS]--;
    							for(int k = 1; k <= cg[i][S]; k++) g[i][S][k] = g[i-1][SS][k];
    						}
    					}
    				}
    //				printf("%d ", i); Bin(S); putchar(' '); printf("%d
    ", f[i][S]);
    			}
    		}
    	
    	for(int S = 0; S <= all; S++) {
    		if(f[maxn-1][maxst-1] < f[n-m+1][S]) {
    			f[maxn-1][maxst-1] = f[n-m+1][S];
    			cg[maxn-1][maxst-1] = cg[n-m+1][S];
    			for(int k = 1; k <= cg[maxn-1][maxst-1]; k++) g[maxn-1][maxst-1][k] = g[n-m+1][S][k];
    		}
    		else if(f[maxn-1][maxst-1] == f[n-m+1][S] && larger(n-m+1, S, maxn-1, maxst-1)) {
    			cg[maxn-1][maxst-1] = cg[n-m+1][S];
    			for(int k = 1; k <= cg[maxn-1][maxst-1]; k++) g[maxn-1][maxst-1][k] = g[n-m+1][S][k];
    		}
    	}
    //	printf("%d
    ", f[maxn-1][maxst-1]);
    	printf("%d
    ", cg[maxn-1][maxst-1]);
    	for(int i = 1; i <= cg[maxn-1][maxst-1]; i++) printf("%d
    ", g[maxn-1][maxst-1][i]);
    	
    	return 0;
    }
    
  • 相关阅读:
    [Contest on 2020.4.2] 影帝杯狂欢赛
    [BZOJ 3821] 玄学
    CodeForces 432D Prefixes and Suffixes
    CodeForces 17E Palisection
    CodeForces 665E Beautiful Subarrays
    BZOJ 2989 数列
    changeeksdja
    Jmeter学习——1
    LoadRunner监控Linux与Windows方法(经典)
    LR检查点小结
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5505949.html
Copyright © 2020-2023  润新知