NOIP2017 题解

QAQ……由于没报上名并没能亲自去,自己切一切题聊以慰藉吧……

可能等到省选的时候我就没有能力再不看题解自己切省选题了……辣鸡HZ毁我青春

D1T1 小凯的疑惑

地球人都会做,懒得写题解了……

D1T2 时间复杂度

分类讨论+递归就行了,没啥思维含量,略。

D1T3 逛公园

这题好劲啊……

D2T1 奶酪

\(O(n^2)\)暴力就行了,水题。

D2T2 宝藏

看到数据范围一眼\(O^*(3^n)\)状压DP,其中\(3^n\)来自枚举子集的子集。做法好像有很多,比如ryf的做法就比我快了10倍……日渐辣鸡的窝

定义\(f_{i,j,S}\)表示以\(i\)为根的子树,\(i\)在整棵树里的深度是\(j\),集合\(S\)中的所有点都在这棵子树中时这棵子树的最小总代价。

不难写出转移方程:

\[f_{i,j,S}=\min_{T\subsetneq S,k\in T}\{f_{k,j+1,T}+f_{i,j,S-T}+j\times w_{i,k}\}\]

(这个转移方程是在枚举与\(i\)相邻的一个点\(k\)并把以\(k\)为根的子树分出去)

然而你发现这个DP是\(O(n^3 3^n)\)的,并不能跑过去。

考虑优化转移,如果把转移方程中与\(S\)无关的部分拿出来并定义一个辅助数组

\[g_{i,j,T}=\min_{k\in T}\{f_{k,j+1,T}+j\times w_{i,k}\}\]

的话,我们就可以把状态转移方程改写成

\[f_{i,j,S}=\min_{T\subsetneq S}\{f_{i,j,S-T}+g_{i,j,T}\}\]

这样就可以把复杂度降到\(O(n^2 3^n)\)了,由于常数不大,并不需要卡常。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define bit(x) (1<<((x)-1))
using namespace std;
const int INF=0x3f3f3f3f;
int n,m,w[15][15],f[15][15][(1<<12)+1],g[15][15][(1<<12)+1];
int main(){
    scanf("%d%d",&n,&m);
    memset(w,63,sizeof(w));
    memset(f,63,sizeof(f));
    memset(g,63,sizeof(g));
    while(m--){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        w[x][y]=w[y][x]=min(w[x][y],z);
    }
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)f[i][j][bit(i)]=0;
    for(int j=n-1;j;j--)for(int s=0;s<(1<<n);s++)for(int i=1;i<=n;i++){
        for(int k=1;k<=n;k++)if((bit(k)|s)==s&&w[i][k]<INF)
            g[i][j][s]=min(g[i][j][s],f[k][j+1][s]+w[i][k]*j);
        for(int t=s&(s-1);;(--t)&=s){
            f[i][j][s]=min(f[i][j][s],f[i][j][s^t]+g[i][j][t]);
            if(!t)break;
        }
    }
    int ans=INF;
    for(int i=1;i<=n;i++)ans=min(ans,f[i][1][(1<<n)-1]);
    printf("%d",ans);
    return 0;
}

D2T3 列队

这题真是劲啊……比往年的数据结构NB到不知哪儿去了……

时间: 2024-08-30 18:03:54

NOIP2017 题解的相关文章

noip2017题解&amp;总结&amp;反省

noip2017是我见过的有史以来最坑爹的一场考试了. 今年北京市考点有一个是我们学校,我还恰好被分到了自己学校(还是自己天天上课的那个教室),于是我同时报了普及提高,一天半的时间都考了. 这次考试总的来说虽然两场都拿了一等奖,但很不满意,从中可以看出我在敲代码学习上还是问题百出. 下面我分两篇来总结. 1.普及组 今年的普及组题目很不良心,我考试的时候周围全是小学生和初一学生...我是少有的几个初三学生中的一个. 普及组的题目,我本来计划ak虐场的,结果被反虐了.不是题不会(每题都是一眼就看出

NOIP2017题解

改题的过程中发现自己的思路有的很接近正解,但总是出了某些思维方式的偏差,所以或许还是写一写题解的好,毕竟游记都记的是一些乱七八糟的旅行经历和心理感受--正好中午饭前只有强行翘掉的一节课,就欣然划水了. Day1 T1<小凯的疑惑> 得分:100 一道数学题,但是最合适的解法是打表找规律.记a为两个数中较小的一个,我打表的方式是对于每一个要check的数枚举$a$和$b$的系数暴力判断可行性,从$a+1$开始check,如果出现了连续的a个可行解就说明后面的每一个数$x$都可以由$(x-a)+1

NOIP2017总结 &amp; 题解

day1t1的结论貌似在哪见过,自己稍微验证了一下貌似没记错就没有管了.t2一道很好(keng)的模拟题t3自己做题好慢啊,想出来dp打上去最后几分钟才过了大样例,我写的是记忆化搜索,判-1很好判,没时间加上去了可惜了,不过还是自己做题太慢了.然后由于没拍,不确定自己dp对不对,就特判了k=0粘了一个暴力,没想到暴力错了,70变成50...基础不扎实gg 100+100+50=250  好菜啊t3没A掉 day2t1看完题就开始打,没注意算距离时减一下就变成两倍了会爆long long,但好像数

TYVJ NOIP2017金秋冲刺训练营杯联赛模拟大奖赛第二轮Day2题解

肝了两题... T1一眼题,分解质因数,找出2的个数和5的个数取min输出 #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int maxn=1000010,inf=1e9; int n,m,T; int fac2[m

tyvj NOIP2017金秋冲刺训练营杯联赛模拟大奖赛第一轮Day2题解

上星期打的...题有点水,好多人都AK了 T1排个序贪心就好了 #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int maxn=500010,inf=1e9; struct poi{int e,s;}a[maxn];

[Luogu 3958] NOIP2017 D2T1 奶酪

NOIP2017 D2T1 奶酪(Luogu 3958) 人生第一篇题解,多多关照吧. 一个比较容易想到的搜索.我用的BFS. 因为涉及到开根,所以记得开double. 首先将所有的球按z值从小到大排序,如果最下方的球与底面相离,或是最上方的球与顶面相离,直接Pass. 接下来预处理,记得先初始化,对于每一组球(i,j),计算两球球心距离是否小于半径×2,用一个bool数组e[i][j]记录i能否到达j,避免BFS时重复计算. 我们会发现,可能不止一个球与底面相切或相交,也可能不止一个球与顶面相

[SinGuLaRiTy] NOIP2017 提高组

[SinGuLaRiTy-1048] Copyright (c) SinGuLaRiTy 2018. All Rights Reserved. NOIP2017过了这么久,现在2018了才找到寒假这么一个空挡来写题解.哎,没办法,谁叫学校抓的紧呢. 序 | Before 这是我的最后一次NOIP. 因为是最后一次的原因吧,考前压力就蛮大的,再加上各种模拟赛,模板练习的轮番轰炸,走进考场时整个人都是“飘飘欲仙”的感觉~ 我的NOIP2017就在这种“飘飘欲仙”的氛围下开始了. 游记 | Blogs

【NOIP2017】列队(Splay)

[NOIP2017]列队(Splay) 题面 洛谷 题解 其实好简单啊... 对于每一行维护一棵\(Splay\) 对于最后一列维护一棵\(Splay\) \(Splay\)上一个节点表示一段区间 每次出去一个人就是把当前的\(Splay\)的一个节点拆分成\(3\)个 然后就很简单了.. 细节比较多.. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #incl

NOIP2017 列队

NOIP2017 列队 题目大意 有一个\(n*m\)的列队方格. 一开始,这个列队中\((i,j)\)的人的编号为\((i-1)m+j\). 每次下达一个指令\((x,y)\),使得\((x,y)\)这个位置的人出列. 然后: 向左看齐,所有人向左填补空位. 向前看齐,所有人向前填补空位. 不难发现两次看齐后空位变到了\((n,m)\),然后令刚才出列的人回到这个位置. 对于依次进行的\(Q\)次指令,你需要输出出列的人的编号. 数据范围:\(n,m,Q \leq 3*10^5\) 前言 NO