10.28.2017(day 1) 考试总结与解题报告

今天的题目不算太难,题目都是一眼就看出解法的,比如第一题并查集或模拟,第二题最小瓶颈路加上最短路,第三题树型Dp,但看出来不意味着会做,尽管第三题一看就是树型Dp,但想了俩小时仍没有正解思路。

今天的题应该是目前为止最接近于NOIP难度的题目了,但相对于NOIP,第一题偏难,第二题偏水,第三题反正不会做,也不知道难度。所以今天的基准分应该在 210

还有50分钟就是 day2 了,赶紧写完前一天的解题报告

抄代码

问题描述
J 君是机房的红太阳,每次模拟她总是 AK 虐场。然而在 NOIP2117 中,居然出现了另一位
AK 的选手 C 君!
这引起了组委会的怀疑,组委会认为 C 君有抄袭 J 君代码的嫌疑,原因是考试时 C 君正好
坐在 J 君旁边。于是组委会需要你帮她们鉴定一下 C 君是否抄了 J 君的代码。
NOIP2117 一共有 T 道题,每道题需要提交一份阿语言代码 (阿语言是 NOIP2117 的唯一可
用编程语言)。
一份阿语言代码只有一行,仅由小写字母,数字,空格和分号组成。
组委会认为,如果 C 君的代码可以由 J 君的代码经过若干次修改变量名操作得到,C 君就
抄了 J 君的代码。
一次修改变量名操作被定义为将代码中的所有小写字母 x 替换为小写字母 y(此处 x, y 代指
任意小写字母)。
请你告诉组委会,对于每道题,C 君是否抄了 J 君的代码。

输入格式
第一行一个正整数 T 。
接下来 2T 行,第 2i 行代表 J 君对于第 i 道题的提交代码,第 2i + 1 行代表 C 君对于第 i
道题的提交代码。

输出格式
输出 T 行,如果对于第 i 道题,C 君抄了 J 君的代码,请在第 i 行输出1,否则请在第 i 行
输出0。

样例输入
5
int x;
int y;
double a;
double aa;
float 1
float 2
string s;
double d;
print thisismycode;
float tooooooooooo;

样例输出
1
0
0
1
1
数据规模与约定
10% 的数据满足代码中不包含字母。
另外 30% 的数据满足代码中只包含字母。
100% 的数据满足 T ≤ 1000,每行代码中不会包含超过 1000 个字符。

思路

这一看就是模拟题吧,想叫贪心也行

主体思路就是若俩字符串儿长度不等,铁定不是抄的

若俩字符至少有一个不是字母,而俩字符不等,铁定不是抄的

若当前俩字符都是字母,但俩字符不等,将前字母hash到后字母上,若已有hash,则匹配,相等继续,不等铁定不是抄的

然而这题dalao们好像想多了,认为有环,但是蒟蒻们都知道,如果要把俩变量名交换,可以用中间变量名作桥

无耻地 贴上代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<deque>
#include<ctime>
using namespace std;
#define cl(x) memset(x,0,sizeof(x))
#define rg register
#define cl1(x) memset(x,-1,sizeof(x))

const int maxt=1001,maxlen=1200;

int hash[200];

char c[10];

int n,T;

int main(){
    freopen("copycat.in","r",stdin);
    freopen("copycat.out","w",stdout);
    scanf("%d",&T);
    gets(c);
    while(T--){
        char a[maxlen],b[maxlen];
        cl1(hash);
        gets(a);
        gets(b);
        int len=strlen(a);
        int flag=0;
        if(strlen(b)!=len){flag=1;printf("0\n");continue;}
        for(rg int i=0;i<len;++i){
            if((a[i]<'a' or a[i]>'z') or (b[i]<'a' or b[i]>'z'))if(a[i]!=b[i]){
                flag=1;
                printf("0\n");
                break;
            }
            if(-1==hash[a[i]]){hash[a[i]]=b[i];continue;}
            else if(hash[a[i]]==b[i])continue;
            flag=1;printf("0\n");break;
        }
        if(flag)continue;
        printf("1\n");
    }
    return 0;
}

做运动

问题描述
一天,Y 君在测量体重的时候惊讶的发现,由于常年坐在电脑前认真学习,她的体重有了突
飞猛进的增长。
幸好 Y 君现在退役了,她有大量的时间来做运动,她决定每天从教学楼跑到食堂来减肥。
Y 君将学校中的所有地点编号为 1 到 n,其中她的教学楼被编号为 S,她的食堂被编号为 T ,
学校中有 m 条连接两个点的双向道路,保证从任意一个点可以通过道路到达学校中的所有点。
然而 Y 君不得不面临一个严峻的问题,就是天气十分炎热,如果 Y 君太热了,她就会中暑。
于是 Y 君调查了学校中每条路的温度 t,及通过一条路所需的时间 c。Y 君在温度为 t 的地
方跑单位时间,就会使她的热量增加 t。
由于热量过高 Y 君就会中暑,而且 Y 君也希望在温度较低的路上跑,她希望在经过的所有
道路中最高温度最低的前提下,使她到达食堂时的热量最低 (从教学楼出发时,Y 君的热量为 0)。
请你帮助 Y 君设计从教学楼到食堂的路线,以满足她的要求。你只需输出你设计的路线中所
有道路的最高温度和 Y 君到达食堂时的热量。

输入格式
第一行由一个空格隔开的两个正整数 n , m,代表学校中的地点数和道路数。
接下来 m 行,每行由一个空格隔开的四个整数 a, b , t, c 分别代表双向道路的两个端点,温度
和通过所需时间。
最后一行由一个空格隔开的两个正整数 S, T ,代表教学楼和食堂的编号。
注意:输入数据量巨大,请使用快速的读入方式。

输出格式
一行由一个空格隔开的两个整数,分别代表最高温度和热量。

样例输入
5 6
1 2 1 2
2 3 2 2
3 4 3 4
4 5 3 5
1 3 4 1
3 5 3 6
1 5

样例输出
3 24

数据规模与约定
10% 的数据满足 t=0
另外 10% 的数据满足 c=0
另外 30% 的数据满足 n2000
100% 的数据满足 n5×105,m106,0t10000,0c108,1a,b,S,Tn,ST

思路

一看就是最小瓶颈图加上最短路,而且不会卡SPFA

但是本蒟蒻傻,傻逼地打了个SPFA和dijkstra+heap,拼接,怕被卡

题解总结起来就是:
(prim || kruskal) && ((dijkstra && heap) || (SPFA && SLF))

代码

这里写代码片#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<deque>
using namespace std;
typedef long long ll;
#define rg register
#define cl(x) memset(x,0,sizeof(x))
#define cl1(x) memset(x,-1,sizeof(x))
#define clm(x) memset(x,0x3f3f3f3f,sizeof(x))
#define inf 2000000001

#define merge(x,y) dad[father(x)]=father(y)
#define check(x,y) (father(x)==father(y))

template <typename _Tp> inline void read(_Tp &x){
    char c11=getchar();x=0;bool booo=0;
    while(c11<'0'||c11>'9'){if(c11=='-')booo=1;c11=getchar();}
    while(c11>='0'&&c11<='9'){x=x*10+c11-'0';c11=getchar();}
    if(booo)x=-x;
}

const int maxn=600050,maxm=1500500;

struct node {int l,r,t,c;} e[maxm];
int maxt=0;
struct node1 {int v,nxt;ll w;}a[maxm<<1];
int dad[maxn],head[maxn],p=0,s,t,n,m;
ll dis[maxn];

inline bool my_comp(const node aa,const node bb){return aa.t<bb.t;}

inline int father(int x){return dad[x]?dad[x]=father(dad[x]):x;}

inline void add(int,int,int);

void init();

void make(){
    sort(e+1,e+m+1,my_comp);
    int poi=1;
    for(rg int i=1;i<=m;++i,++poi){
        if(!check(e[i].l,e[i].r))merge(e[i].l,e[i].r);
        if(check(s,t)){
            while(e[i+1].t==e[i].t)++i,++poi;
            break;
        }
    }
    if(poi>m)return ;
    maxt=e[poi].t;
    for(rg int i=1;i<=poi;++i)
    add(e[i].l,e[i].r,(ll)e[i].t*e[i].c),add(e[i].r,e[i].l,(ll)e[i].t*e[i].c);
}

void spfa(){
    deque <int> q;
    q.push_back(s);
    clm(dis);
    dis[s]=0;
    while(!q.empty()){
        int x=q.front();
        q.pop_front();
        for(rg int i=head[x];i;i=a[i].nxt)
        if(dis[x]+a[i].w<dis[a[i].v]){
            if(dis[a[i].v]<dis[q.front()])q.push_front(a[i].v);
            else q.push_back(a[i].v);
            dis[a[i].v]=dis[x]+a[i].w;
        }
    }
}

#define get(x) dis[x]
int str[maxn<<2],top=0;
inline void push(int x){
    str[++top]=x;
    rg int pp=top;
    while(pp>1&&get(str[pp])<get(str[pp>>1])){swap(str[pp],str[pp>>1]);pp>>=1;}
    return ;
}

inline void pop(){
    str[1]=str[top--];
    rg int pp=1;
    while(((pp<<1)<=top&&get(str[pp])>get(str[pp<<1]))||((pp<<1|1)<=top&&get(str[pp])>get(str[pp<<1|1]))){
        pp<<=1;
        if(get(str[pp])>get(str[pp|1]))pp|=1;
        swap(str[pp],str[pp>>1]);
    }
    return ;
}
bool boo[maxn];
void dijkstra(){
    clm(dis);
    cl(boo);
    dis[s]=0;
    push(s);
    for(rg int i=1;i<=n;++i){
        if(str[1]==t&&top)return ;
        while(boo[str[1]]&&top)pop();
        if(!top)return ;
        int x=str[1];pop();
        boo[x]=1;
        for(rg int j=head[x];j;j=a[j].nxt)
            if(dis[x]+a[j].w<dis[a[j].v])dis[a[j].v]=dis[x]+a[j].w,push(a[j].v);
    }
}
int ff=0;
int main(){
    freopen("running.in","r",stdin);
    freopen("running.out","w",stdout);
    init();if(!ff){puts("0 0\n");return 0;}
    make();
    if(0&&m<5*n)
        spfa();
    else
        dijkstra();
    printf("%d %lld\n",maxt,dis[t]);
    return 0;
}

void init(){
    read(n);read(m);cl(head);cl(dad);
    for(rg int i=1;i<=m;++i){read(e[i].l);read(e[i].r);read(e[i].t);read(e[i].c);if(e[i].t)ff=1;}
    read(s);read(t);
}

inline void add(int u,int v,int w){
    a[++p].v=v;
    a[p].w=w;
    a[p].nxt=head[u];
    head[u]=p;
}

大逃杀

问题描述
自从 Y 君退役之后,她就迷上了吃鸡,于是她决定出一道吃鸡的题。
Y 君将地图上的所有地点标号为 1 到 n,地图中有 n − 1 条双向道路连接这些点,通过一条
双向道路需要一定时间,保证从任意一个点可以通过道路到达地图上的所有点。
有些点上可能有资源,Y 君到达一个有资源的点后,可以选择获取资源来使自己的武力值增
加 w i ,也可以选择不获取资源。如果 Y 君获取了一个点上的资源,这个点上的资源就会消失,获
取资源不需要时间。
有些点上可能有敌人,Y 君到达一个有敌人的点后,必须花费 t i 秒伏地与敌人周旋,并最终
将敌人消灭。如果 Y 君消灭了一个点上的敌人,这个点上的敌人就会消失。Y 君不能无视敌人继
续前进,因为这样会被敌人攻击。
如果一个点上既有资源又有敌人,Y 君必须先消灭敌人之后才能获取资源,否则就会被敌人
突袭。
游戏开始时,Y 君可以空降到任意一个点上,接下来,她有 T 秒进行行动,T 秒后她就必须
前往中心区域送快递。Y 君希望她前往中心区域送快递时,武力值尽可能大,请你帮助 Y 君设计
路线,以满足她的要求。你只需输出 T 秒后 Y 君的武力值。

输入格式
第一行由单个空格隔开的两个正整数 n, T ,代表点数和时间。
第二行 n 个由单个空格隔开的非负整数代表 wi ,如果 wi=0 代表该点没有武器,
第三行 n 个由单个空格隔开的非负整数代表 ti ,如果 ti=0 代表该点没有敌人。
接下来 n − 1 行每行由单个空格隔开的 3 个非负整数 a, b, c 代表连接 a 和 b 的双向道路,通
过这条道路需要 c 秒。

输出格式
输出一行一个整数代表 T 秒后 Y 君的武力值。

样例输入
17 54
5 5 1 1 1 25 1 10 15 3 6 6 66 4 4 4 4
0 1 3 0 0 0 1 3 2 0 6 7 54 0 0 0 0
1 8 3
2 8 3
8 7 7
7 13 0
7 14 0
15 14 2
16 14 3
17 14 5
7 9 4
9 10 25
10 11 0
10 12 0
7 6 20
3 6 3
3 4 3
3 5 3

样例输出
68

数据规模与约定
有些部分分特殊性质就不写了,只想正解(实际上是因为我不会插入表格)
100% 的数据满足 n, T ≤ 300, 0 ≤ w i , t i , c ≤ 10 6 , 1 ≤ a, b ≤ n。

思路

首先要肯定一点,就是这题是树型Dp的题

看下数据规模,就知道这题不可能 n <script type="math/tex" id="MathJax-Element-20">n</script>遍树型Dp过,就一定要一遍过

想想原来的树型Dp方程,其实可以加一个数组就可以实现一遍更比六遍强

就是h数组,表示从x的子树出来又进去

看看代码吧:

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#include<climits>
using namespace std;

#define rg register
#define cl(x) memset(x,0,sizeof(x))
#define clm(x) memset(x,0x3f3f3f3f,sizeof(x))
#define inf 0x3f3f3f3f

template <typename _Tp> inline void read(_Tp &x){char c11=getchar();x=0;
    while(c11<'0'||c11>'9')c11=getchar();while(c11>='0'&&c11<='9'){x=x*10+c11-'0';c11=getchar();}
}

const int maxn=350,maxm=350,maxt=350;
struct node{int v,w,nxt;} a[maxm<<1];
int head[maxn],p=0;
int w[maxn],v[maxn],T,n;
int f[maxn][maxt],g[maxn][maxt],h[maxn][maxt];
int ans=0;

inline void add(int,int,int);

void init();

void dfs(int x, int las){
    for(rg int i=0;i<=T;++i)
        f[x][i]=g[x][i]=h[x][i]=(i>=w[x]?v[x]:-inf);
    for(rg int i=head[x];i;i=a[i].nxt)
        if(a[i].v!=las){
            dfs(a[i].v,x);
            int e=a[i].w,s=a[i].v;
            for(rg int j=T;j>=e;--j)
            for(rg int k=0;k<=j-e;++k){
                int tf = f[x][j], tg = g[x][j], th = h[x][j];
                if(j-k-2*e >= 0){
                    tf = max(tf, f[x][j-k-2*e]+f[s][k]);
                    tg = max(tg, g[x][j-k-2*e]+f[s][k]);
                    th = max(th, h[x][j-k-2*e]+f[s][k]);
                    th = max(th, f[x][j-k-2*e]+h[s][k]);
                }
                tg = max(tg, f[x][j-k-e]+g[s][k]);
                th = max(th, g[x][j-k-e]+g[s][k]);
                f[x][j] = tf, g[x][j] = tg, h[x][j] = th;
            }
        }
    ans = max(ans, h[x][T]);
}

void work(){
    dfs(1,0);
    printf("%d\n",ans);
    return ;
}

int main(){
    freopen("toyuq.in","r",stdin);
    freopen("toyuq.out","w",stdout);
    srand(time(0));
    init();
    work();
    return 0;
}

void init(){
    cl(head);
    read(n);read(T);
    for(rg int i=1;i<=n;++i)read(v[i]);
    for(rg int i=1;i<=n;++i)read(w[i]);
    int A,B,C;
    for(rg int i=1;i<n;++i){
        read(A);read(B);read(C);
        add(A,B,C);add(B,A,C);
    }
    return ;
}

inline void add(int u,int v,int w){
    a[++p].v=v;
    a[p].w=w;
    a[p].nxt=head[u];
    head[u]=p;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值