zoukankan      html  css  js  c++  java
  • 「雅礼集训 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;
    }
  • 相关阅读:
    SCRUM第一天
    第八周总结
    第7周总结
    团队项目nabcd
    人月神话1
    课堂练习之四则运算
    第六周总结
    Storm Grouping —— 流分组策略
    抓取网页内容生成Kindle电子书(转)
    浅析PageRank算法(转)
  • 原文地址:https://www.cnblogs.com/XYZinc/p/8665877.html
Copyright © 2011-2022 走看看