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;
    }
  • 相关阅读:
    js生成cron表达式
    原生table控制tbody滚动而thead不滚动
    js记性
    oracle 多库表建立dblink查询
    java操作mysql数据库备份
    java 抓取网页的图片
    ZOJ 3485 Identification Number【模拟】【暴力】
    Codeforces 1037E Trips【图论】【dfs】
    Codeforces 1036C Classy Numbers 【数位dp】
    Codeforces 1036B Diagonal Walking v.2 【贪心】
  • 原文地址:https://www.cnblogs.com/XYZinc/p/8665877.html
Copyright © 2011-2022 走看看