• NOIP 2017-day2


    pts: 120

    T1: 100

    T2: 20

    T3: 0

    前言:瞅了一样 T3,区间删除和插入(据说是平衡树板子,可我不会平衡树啊/kk),去干 T2 ,为啥 T2 也炸了啊 /jk

    总结:卷数据结构去 = =

    T1

    奶酪

    搜索,并查集

    solution

    逃不过立体几何

    不止岛为啥他们都在写搜索 = = 这不是并查集的大板子嘛

    对于能连起来的洞用并查集并到一起,最后两两枚举能打通上边界的洞和下边界的洞是否能连起来就好了哇

    两个球是否连接的条件:

    两个球心的距离 (leq 2 * r)

    code

    /*
    work by:Ariel_  
    */
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define int long long
    using namespace std;
    const int N = 1000 + 5;
    int read(){
        int x = 0,f = 1; char c = getchar();
        while(c < '0'||c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') {x = x*10 + c - '0'; c = getchar();}
        return x*f;
    }
    struct Pots{int x, y, z;}a[N];
    int fa[N];
    int find(int x) {return fa[x] == x ? fa[x] : find(fa[x]); }
    int merage(int x, int y){fa[find(x)] = find(y);}
    int calc(int p, int o) {
       return (a[o].x - a[p].x) * (a[o].x - a[p].x) + (a[o].y - a[p].y) * (a[o].y - a[p].y) + (a[o].z - a[p].z) * (a[o].z - a[p].z); 
    }
    int T, n, h, r, l_id[N], r_id[N], cnt_l, cnt_r, fag;
    void clear(){
       memset(l_id, 0, sizeof l_id);
       memset(r_id, 0, sizeof r_id);
       cnt_l = 0, cnt_r = 0, fag = 0;
    }
    signed main(){
       T = read();
       while(T--) {
       	  n = read(), h = read(), r = read();
       	  for (int i = 1; i <= n; i++) a[i].x = read(), a[i].y = read(), a[i].z = read();     
          for (int i = 1; i <= n; i++) fa[i] = i;
          clear();
    	  for (int i = 1; i <= n; i++) {
    	     if (a[i].z + r >= h) r_id[++cnt_r] = i;
    	     if (a[i].z - r <= 0) l_id[++cnt_l] = i;
    	     for (int j = 1; j <= i; j++)
    	       if(calc(i, j) <= 4 * r * r) merage(i, j);
    	  }
    	  for (int i = 1; i <= cnt_l; i++){
    	  	for (int j = 1; j <= cnt_r; j++)
    	  		  if (find(l_id[i]) == find(r_id[j])){fag = 1; break;}
    		if(fag) break;
          }
          if(fag) printf("Yes
    ");
          else printf("No
    ");
       }
       return 0;
    }
    

    T2

    [NOIP2017 提高组] 宝藏

    贪心,枚举,暴力,状压 dp

    solution

    20 pts

    树的情况,求出树的重心,对每个点跑最短路,然后更新答案就好了

    70 pts

    (n = 8) 真滴很小啊,直接枚举起点和开采顺序就好了 /kk

    然后,直接枚举每个点由哪个点转移来的就好了

    code

    /*
    work by:Ariel_
    */
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #define int long long
    using namespace std;
    const int INF = 0x3f;
    int read(){
        int x = 0,f = 1; char c = getchar();
        while(c < '0'||c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') {x = x*10 + c - '0'; c = getchar();}
        return x*f;
    }
    int n, m, e[55][55], f[55], ans = 2147483645, tmp;
    void dfs(int num){
       if (num == n) {
       	  ans = min(ans, tmp);
       	  return ;
       }
       if(tmp >= ans) return ;
       for (int i = 1; i <= n; i++) {
       	   if(f[i]) continue;
       	   for (int j = 1; j <= n; j++) {
       	   	   if(e[j][i] == 2147483645 || !f[j] || i == j) continue;
    		   tmp += f[j] * e[j][i]; f[i] = f[j] + 1;
    		   dfs(num + 1);
    		   f[i] = 0; tmp -= f[j] * e[j][i]; 
    		}
       }  
    }
    signed main(){
       n = read(), m = read();
        for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
          e[i][j] = 2147483645;																											
       for (int i = 1; i <= m; i++) {
       	  int u = read(), v = read();
       	  e[u][v] = e[v][u] = min(e[u][v], read());
       }
       for(int i = 1; i <= n; i++)
       	 f[i] = 1, dfs(1), f[i] = 0;
       printf("%lld", ans);
       puts("");
       return 0;
    }
    

    100 pts

    搜索剪枝能过 ??

    还是看看状压吧

    题目可以看做找一个点作为根,生成一棵树,满足代价 $sum dep[i] * dis[fa_i][i] $ 最小

    其中 (dep_i) 表示 (i) 节点在这棵生成树中的深度(根节点深度为 (0), (dis[fa_i][i]) 表示 (i) 节点到他父亲节点的距离

    因为 (n leq 12) 所以考虑状压节点

    状态:

    (f[i]) 表示所选点的集合为 (i) 的最小花费,(st_{i,j}) 表示当前选的点的集合为 (i) 并且 (i) 状态取最优方案时,节点 (j) 的深度

    转移:

    (f_{i∣2^{k}} = min({f_{i∣2^k},f_i + (dis[j][k] ∗ (st[i][j]+1))})

    (st_{i∣2^k} =st_{i,j}+1(j∈i~~&~~k otin i))

    初始化:(f_{2^S} = 0, st_{{2^s},s} = 0)

    时间复杂度

    (O(n^3 imes 2^n))

    code

    /*
    work by:Ariel_
    */
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <algorithm>
    using namespace std;
    const int N = 15;
    int read(){
        int x = 0,f = 1; char c = getchar();
        while(c < '0'||c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') {x = x*10 + c - '0'; c = getchar();}
        return x*f;
    }
    int dis[N][N], st[1 << N][N], f[1 << N], n, m, ans = 0x3f3f3f3f;
    int work(int s){
       memset(f, 0x3f, sizeof f), memset(st, 0x3f, sizeof st);
       int lim = (1 << n);
       f[1 << s] = 0; st[1 << s][s] = 0;
       for (int i = 1; i < lim; i++){//枚举合法状态 
            if(f[i] >= 0x3f3f3f3f) continue;
    		for (int j = 0; j < n; j++) { 
    		  if(!(i & (1 << j))) continue;
    		  for (int k = 0; k < n; k++) {
    		  	 if(i & (1 << k)) continue;
    		  	 if((dis[j][k] != 0x3f3f3f3f) && (f[i|(1 << k)]) > f[i] + (dis[j][k] * (st[i][j] + 1))){
    		  	 	   f[i | (1 << k)] = f[i] + (dis[j][k] * (st[i][j] + 1));
    		  	 	   memcpy(st[i | (1 << k)], st[i], sizeof(st[i | (1 << k)]));
                      st[i | (1 << k)][k] = st[i][j] + 1;
    			   }
    		  }
    		}      
    	} 
    	return f[lim - 1];
    }
    int main(){
       n = read(), m = read();
       memset(dis, 0x3f, sizeof dis);
       for (int i = 1, u, v, w; i <= m; i++) {
       	  u = read(), v = read(), w = read();
       	  u--, v--;//方便二进制 
       	  dis[u][v] = min(dis[u][v], w); dis[v][u] = min(dis[v][u], w);
       }
       for (int i = 0; i < n; i++)//枚举根节点 
         ans = min(ans, work(i));
       printf("%d", ans);
       puts("");
       return 0;
    }
    

    T3

    [NOIP2017 提高组] 列队

    线段树,平衡树,树状数组

    emm……

    等学完平衡树再来写

  • 相关阅读:
    阿里云高级技术专家周晶:基于融合与协同的边缘云原生体系实践
    Spring Boot Serverless 实战系列“架构篇” 首发 | 光速入门函数计算
    基于 EMR OLAP 的开源实时数仓解决方案之 ClickHouse 事务实现
    【ClickHouse 技术系列】 在 ClickHouse 中处理实时更新
    LeetCode_Two Sum
    LeetCode_ Remove Element
    LeetCode_Same Tree
    LeetCode_Symmetric Tree
    LeetCode_Path Sum
    LeetCode_Merge Sorted Array
  • 原文地址:https://www.cnblogs.com/Arielzz/p/14865714.html
Copyright © 2020-2023  润新知