[计蒜客NOIP模拟赛]2017.7.28Day1回顾反思总结

D1T1 打地鼠

题目链接

反思-

比赛得分-0

思考:

比赛时,以为T1是一道常规模拟题目,没怎么看数据范围。直接手动模拟,模拟完之后太自信也没有造数据Hack自己的程序。直接导致爆0。同时发现自己对二维前缀和的学习也只是在皮毛之上,没有深入思考与理解。

解题思路-

将图像旋转45°之后用二维前缀和维护,每次O(1)查询,时间复杂度O(N*N)。

但是目前觉得这个图像旋转45°难以理解,打算手动模拟加深理解。

标程

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int a[4050][4050],b[4050][4050],s[4050][4050],vis[4050][4050];
int main(){
    //freopen("mouse10.in","r",stdin);
    //freopen("mouse10.ans","w",stdout);
    scanf("%d%d%d",&n,&k);m=n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&a[i][j]);
    int l=n+n-1,ll=2*l-1;
    for(int i=1;i<=ll;i++){
        if(i>=n&&(i-n)%2==0){
            int num=(i-n)/2+1;
            //if(i==9) cout<<num<<endl;
            for(int j=num;j<=num+n-1;j++)
                b[j][i+1-j]=a[j-num+1][num],vis[j][i+1-j]=1;
        }
    }
    for(int i=1;i<=l;i++)
        for(int j=1;j<=l;j++)
            s[i][j]=b[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
    int ans=0;
    for(int i=1;i<=l;i++)
        for(int j=1;j<=l;j++)
            if(vis[i][j]){
                int zsx=max(1,i-k+1),zsy=max(1,j-k+1),zxx=min(l,i+k-1),zxy=max(1,j-k+1);
                int ysx=max(1,i-k+1),ysy=min(l,j+k-1),yxx=min(l,i+k-1),yxy=min(l,j+k-1);
                ans=max(ans,s[yxx][yxy]-s[ysx-1][yxy]-s[zxx][zxy-1]+s[zsx-1][zsy-1]);
        }
    printf("%d\n",ans);
}

D1T2 蒜头君的树

反思-

比赛得分-30

思考:

比赛时,以为是用数据结构维护,生硬套上了树剖模板,但是得分只有30。没有深入去思考,每个变化的边的所带来的影响。

解题思路-

乘法原理在树上的运用,我们假设结点u是结点v的父亲,其边权为w。那么这条边权会被最终答案计算多少次呢?没错就是除儿子v及其子结点的数量*儿子v及其子结点的数量。

修改的话只考虑,修改的那条边对其他结点的影响。 我们假设修改的结点是 x,那么影响的结点数量就是x及其子孙数量*其他结点数。

#include <cstdio>
#include <algorithm>
#include <vector>
typedef long long ll;
const int maxn = 1e5+5;

struct node{
    int v,w;
};

std::vector<node>G[maxn];
int n,m,bian[maxn];
ll sum[maxn],dp[maxn];

int Read(){
    int ch = 0;
    char c;
    c = getchar();
    while( c<‘0‘ || c>‘9‘) c = getchar();
    while( c>=‘0‘ && c<=‘9‘) {
    ch = ch*10+c-‘0‘;
    c = getchar();
    }
    return ch;
}

void dfs(int x,int fa){
    sum[x] = 1;
    int Size = G[x].size();
    for(int i=0;i<Size;i++){
        int v = G[x][i].v;
        int w = G[x][i].w;
        if(v==fa) continue;
        dfs(v,x);
        sum[x]+=sum[v];
        dp[x]+=(dp[v]+((n-sum[v])*sum[v])*w); //关键部分
    }
}

void AddEdge(int u,int v,int w){
    node now;
    now.v=v;
    now.w=w;
    G[u].push_back(now);
    now.v=u;
    G[v].push_back(now);
}

int main(){
    n = Read();
    for(register int i=1;i<n;i++){
        int v,w;
        v = Read();
        w = Read();
        AddEdge(i+1,v,w);
        bian[i+1]=w;
    }
    dfs(1,0);
    printf("%lld\n",dp[1]);
    m = Read();
    for(int i=1;i<=m;i++){
        int x,y;
        x = Read();
        y = Read();
        ll ans = dp[1]+sum[x]*(n-sum[x])*(y-bian[x]);//只考虑修改的边影响的结果
        bian[x] = y;
        dp[1] = ans;
        printf("%lld\n",ans);
    }
    return 0;
}

D1T3 蒜头君的坐骑

题目链接

反思-

比赛得分-0

思考:

比赛时,在T2耗费了两小时,这个时间没有时间思考了。所以草草写了一个我自己都看不懂的辣鸡暴力,成功爆0!

解题思路-

暴力搜索30分

用dp[n][m][k]表示牛神现在在(n,m)点,已经使用了k次技能.对于每次决策,如果不使用技能,可以转移到dp[n][m+1][k],dp[n+1][m][k],如果使用技能,则可通过dfs搜索可以转移到的每一个点,时间复杂度O(n*m*k).

不得不说这是第一次见到用DFS来求DP值,算是大开眼界了。反反复复阅读与抄写了四遍之后。看懂了,DFS和DP的含义。

#include<bits/stdc++.h>
using namespace std;
int n,m,t,k,h,atk;
int dp[1050][1050][15],mp[1050][1050];
int cal(int x,int y,int at){
     //计算怪物对你造成的伤害 h-1的原因是如果h==at那么应该是秒杀不造成伤害
    return (h-1)/at*mp[x][y];
}
void dfs(int x,int y,int res,int st,int at,int dam){
    if(st) dam+=cal(x,y,at); //在使用技能时,应计算是否受到伤害
    //更新最终停止在x,y点的使用技能情况下的最小伤害值 太妙了
    if(st==k) {dp[x][y][res+1]=min(dp[x][y][res+1],dam);return;}
    if(x+1<=n) dfs(x+1,y,res,st+1,at+mp[x+1][y],dam);//往下走的情况
    if(y+1<=m) dfs(x,y+1,res,st+1,at+mp[x][y+1],dam);//往右走的情况
}
int main(){
    scanf("%d%d%d%d%d%d",&n,&m,&t,&k,&h,&atk);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&mp[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int l=0;l<=t;l++)
                dp[i][j][l]=999999999;
    //在起点没有使用过技能所以为0
    dp[1][1][0]=0;
    for(int l=0;l<=t;l++)
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
                //先考虑如果不使用技能,往下走的情况的最小伤害
                if(i+1<=n)
                dp[i+1][j][l]=min(dp[i+1][j][l],dp[i][j][l]+cal(i+1,j,atk));
                //不使用技能,往右走的最小伤害
                if(j+1<=m)
                dp[i][j+1][l]=min(dp[i][j+1][l],dp[i][j][l]+cal(i,j+1,atk));
                //如果技能还没使用完 那么就考虑一下在此点使用技能之后的情况
                if(l!=t)
                dfs(i,j,l,0,atk,dp[i][j][l]);
            }
    cout<<dp[n][m][t]<<endl;
}

最终总结反思

技不如人就是事实,没有天赋还天天颓。再这样下去,NOIP一等都是一个问题,所以拼命努力吧~

还有就是考试技巧非常重要,多参加比赛练习赛感,减少比赛失误!!!

时间: 2024-08-02 11:03:20

[计蒜客NOIP模拟赛]2017.7.28Day1回顾反思总结的相关文章

计蒜客NOIP模拟赛4 D2T1 鬼脚图

鬼脚图,又称画鬼脚,在日本称作阿弥陀签,是一种经典游戏,也是一种简易的决策方法,常常用来抽签或决定分配组合. 下图就是一张鬼脚图,其包含若干条竖线和若干条横线.请注意,横线只能水平连接相邻的两条竖线,且 在同一高度只会有一条横线. 在图的上方,我们将这 n 条竖线依次标号为 1 到 n.以数字 3 为例,它会沿着所在的竖线下降,期间如果 遇到横线就会移动到横线的另一端,最终降落至下面的第一条竖线.上图中还标出了另外几种数字的最终位置.奇特的是,开始时每条竖线上都有一个数字,而 最终每条竖线下还是

计蒜客NOIP模拟赛(3)D1T3 任性的国王

X 国的地图可以被看作一个两行 nn 列的网格状图.现在 X 国需要修建铁路,然而该国的国王非常小气,他只想保证位于某两列之间的所有城市互相可以到达就行了,在此基础上,他希望所花费的代价最小. 铁路可以建在任何两个相邻的点之间,使他们可以互相到达.可以作为工作人员,你已经整理出了为每一对相邻城市架设铁路所需要的花费.你需要准备好回答国王如下形式的问题. 对于 (i,j)(i,j):当前情况下,使第 ii 列到第 jj 列之间的所有城市连通的最小代价是多少(列下标从 11 开始)?注意不能用其他列

计蒜客NOIP模拟赛D2T3 数三角形

刚刚上高中的洁洁在学习组合数学的过程中遇到一道麻烦的题目,她希望你能帮助她解决.给定一张无向完全图 G,其中大部分边被染成蓝色,但也有一些边被染成红色或者绿色.现在,洁洁需要给这张图的多样性进行打分.一张图的多样性取决于它的同色和异色三角形的个数.具体来说,G 中每有一个三边颜色都互不同的三角形(异色三角形)可以得 3 分,每有一个三边颜色都相同的三角形(同色三角形)则要被扣掉 6 分,其它三角形不得分也不扣分. 现在,请你写一个程序来计算 G 的多样性分数.输入格式 第一行两个正整数 n 和

计蒜客NOIP模拟赛(3) D1T2 信息传递

一个数据包在一个无向网络中传递.在时刻0,该数据包将依照特定的概率随机抵达网络中的某个节点.网络可以看做一张完全带权无向图,包含N个节点,若t时刻数据包在节点i,则在t+1时刻,数据包被传递到节点j的概率是 d(i,j)/(∑kd(i,k))其中d(i,j)表示节点i到节点j的最短路径的长度.在传递到下一个节点后,该数据包会自动删除在当前节点的备份.现在,给定数据包0时刻在每个节点的概率和网络的每条边权.求T时刻数据包在每个节点的概率.输入格式第一行两个整数N和T.第二行N个实数,表示0时刻数据

计蒜客NOIP模拟赛4 D1T2小X的密室

小 X 正困在一个密室里,他希望尽快逃出密室. 密室中有 N 个房间,初始时,小 X 在 1 号房间,而出口在 N 号房间. 密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会单向地创造一条从房间 X 到房间 Y 的通道.另外,想要通过某个传送门,就必须具备一些种类的钥匙(每种钥匙都要有才能通过).幸运的是,钥匙在打开传送门的封印后,并不会消失. 然而,通过密室的传送门需要耗费大量的时间,因此,小 X 希望通过尽可能少的传送门到达出口,你能告诉小 X 这个数值吗? 另外,小 X 有可能

计蒜客NOIP模拟赛4 D1T3 小X的佛光

小 X 是远近闻名的学佛,平日里最喜欢做的事就是蒸发学水. 小 X 所在的城市 X 城是一个含有 N 个节点的无向图,同时,由于 X 国是一个发展中国家,为了节约城市建设的经费,X 国首相在建造 X 城时只建造 N – 1 条边,使得城市的各个地点能够相互到达. 小 X 计划蒸发 Q 天的学水,每一天会有一名学水从 A 地走到 B 地,并在沿途各个地点留下一个水塘.此后,小 X 会从 C 地走到 B 地,并用佛光蒸发沿途的水塘.由于 X 城是一个学佛横行的城市,学水留下的水塘即使没有被小 X 蒸

计蒜客NOIP模拟赛4 D2T2 跑步爱天天

YOUSIKI 在 noip2016 的一道<天天爱跑步>的题爆零后,潜心研究树上问题,成为了一代大师,于是皮皮妖为了测验他,出了一道题,名曰<跑步爱天天>. 有一个以 1 为根的有根树,初始每个点都有个警卫,每个警卫会按深度优先的顺序周期性的巡逻以其初始点为根的子树(详见样例解释),一个时刻走且仅走一条边. YOUSIKI 初始在 x 点,他要到根结点拜访皮皮妖,他会沿着最短路径走,一个时刻走且仅走一条边,当他走到这个点时,如果遇到了警卫,他会消耗 1点妖气将这个警卫杀死,杀死后

复习---归并排序求逆序对--计蒜客2017noip模拟赛二--蒜头君的排序

题目链接:https://nanti.jisuanke.com/t/16443 我不会矩阵快速幂,所以只拿了60分, 发现归并排序掌握的并不熟练,借此良机复习一下. 重在归并排序分治思想,要牢记! #include<iostream> #include<cstring> using namespace std; int n,m,a[30005],s[30005],ans,d[30005]; void msort(int l,int r) { if(l==r)return;//如果只

计蒜课 八月模拟赛题解

看见机房有大佬上周写了上面的普及信心赛 于是我康了康 8月的提高组模拟赛 9月的还没开始qwq 真的 有点难 主要是我先打开了T2 我再次 对自己的数学产生了怀疑 我现在还是不会写T2 T1 又又又又都错题了 下次重建图 尽量写vector 都写 邻接表 变量差不多的容易搞混 我这个同学变又写错了 T1 :https://nanti.jisuanke.com/t/41086 题目大意就是 一个有向图 删一个点 把与他直接和间接 相连的点 删掉 然后 求删掉所有点的最小最大代价 : 为了避免这个环