• 「雅礼集训 2017 Day7」


    蛐蛐国的修墙方案

    loj6043

    从 i 向 p[i] 连边,因为 p 为 1~n 的排列,所以所有点的出度入度皆为 1

    数据保证有解且 p[i] != i,所以建成的图必为多个互不相交的环

    考虑到环内各点相互限制,枚举任一条边是否选择即可确定整个环的状态

    优先将左括号放在前面,这样更容易得到合法的序列

    暴搜

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define N 105
    
    int n, p[N], sel[N];//sel为 1/2 分别代表 左/右 括号 
    bool f[N], vis[N];
    vector<int> to[N];
    
    void dfs(int x, int cnt)//cnt记录括号的配对情况,左括号 +1 右括号 -1 
    {
    	if(cnt < 0 || cnt > n - x + 1) return;
    	if(x > n)
    	{
    		if(cnt != 0) return;//左右括号个数不等 
    		for(int i = 1; i <= n; i++)
    			if(sel[i] == 1) printf("("); else printf(")");
    		exit(0); 
    	}
    	if(sel[x]) {dfs(x + 1, cnt + (sel[x] == 1? 1 : -1));return;}
    	for(int i = 1; i <= 2; i++)//枚举当前位置的括号选择情况 
    	{
    		int cur = x, now = i, len = 0;
    		do
    		{
    			len++;
    			sel[cur] = now;
    			cur = p[cur];
    			now = 3 - now;
    		}while(cur != x);
    		if(len == 2) {dfs(x + 1, cnt + 1); return;}//大小为2的环显然确定 
    		dfs(x + 1, cnt + (sel[x] == 1? 1 : -1));
    		do
    		{
    			sel[cur] = 0;
    			cur = p[cur];
    		}while(cur != x);
    	}
    }
    
    int main()
    {
    	freopen("C.in", "r", stdin);
    	freopen("C.out", "w", stdout);
    	
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i++) scanf("%d", &p[i]);
    	dfs(1, 0);
    	return 0;
    }
  • 相关阅读:
    poj 2676 Suduku (dfs)
    poj 1562 Oil Deposits (dfs)
    poj 2907 Collecting Beepers (dfs)
    poj 1655 Balancing Act (树形dfs)
    poj 3411 Paid Roads (dfs)
    hdu 2896 病毒侵袭 (AC)
    hdu 3065 病毒侵袭持续中 (AC)
    poj 2251 Dungeon Master (bfs)
    java中debug使用
    Swing入门级小项目总结
  • 原文地址:https://www.cnblogs.com/XYZinc/p/8665877.html
Copyright © 2020-2023  润新知