10月集训test13
来源:互联网 发布:qq手机壁纸软件 编辑:程序博客网 时间:2024/05/29 10:42
终于不是地主家的傻儿子企鹅豆豆了。。。
今天是运动会的第一天,锣鼓喧天,热闹非凡。。。而我在考试。。
呵呵。
然而还是感谢WKL凯爷对题的讲解以及详尽的分析。
上题。
1.抄代码
给出几个字符串,两个一组,若其中一个字符串能够由另一个经过多次变换得到,则输出1,否则输出0。
变换的意思是指将字符串中的所有小写字母x变为y(此处x,y代指任意小写字母)
字符串仅由小写字母,数字,空格和分号组成。
输入格式
第一行一个整数T。
接下来2T行,每2i行代表一组字符串。
输出格式
输出T行,若能变换输出1,否则输出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
关于这道题,真的不知道应该说什么。。。。。。
其实可能并不难。。吧。。毕竟连出题的人都没有考虑全所有情况,题解都是错的,但是对于这道题的数据来说足够了。
嗯,长度不一样不能换,非小写字母为不一样不能换,同一小写字母对的不一样不能换。
但是还是少了可能性:
abcdefghijklmnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcba
这样应该是换不了的。(不过鉴于数据干脆就不考虑了吧。)
#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>using namespace std;int t,len1,len2;bool f;char a[1010],b[1010],aa[50];inline int read(){ int i=0;char c; for(c=getchar();c<'0'||c>'9';c=getchar()); for(;c>='0'&&c<='9';c=getchar()) i=(i<<1)+(i<<3)+c-'0'; return i;}int main(){ //freopen("copycat.in","r",stdin); //freopen("copycat.out","w",stdout); t=read(); while(t--) { memset(aa,0,sizeof(aa)); f=1; gets(a);gets(b); len1=strlen(a); len2=strlen(b); if(len1!=len2) { cout<<0<<endl; continue; } for(int i=0;i<len1;i++) if(a[i]!=b[i]) { if(a[i]<'a'||a[i]>'z'||b[i]<'a'||b[i]>'z') {f=0;break;} if(!aa[a[i]-'a']) aa[a[i]-'a']=b[i]; else if(aa[a[i]-'a']!=b[i]) {f=0;break;} } cout<<f<<endl; } return 0;}
2.做运动
Y要从教学楼跑到食堂。
学校为一个无向图,每条路的温度为t,通过的时间为c,Y在温度为t的路上走单位时间,热量增加t。
给出教学楼和食堂的位置,在经过的所有道路中最高温度最低的前提下,使Y到达食堂时的热量最低。(原热量为0)
输入格式
第一行两个正整数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
这道题共有两种做法。
由于以最高温度最低为前提,则重点在温度上。
二分温度,跑一遍dfs判断图是否连通,若连通最高温度再降低,否则升高。最后跑一遍最短路Dijkstra
或者将所有边按温度大小排序加入,用并查集维护S到T的连通性,在第一个连通的温度下跑一遍Dijkstra
注意第二种方法加边时,同一温度的多条边要同时加入。
//二分温度,用dfs判是否连通,若连通跑一遍 dijkstra//按温度从小到大加边,注意同一温度的要同时加,用并查集判是否连通,跑一遍dijkstra #include<iostream>#include<cstdlib>#include<cstdio>#include<ctime>#include<cmath>#include<cctype>#include<iomanip>#include<algorithm>#include<cstring>#include<string>#include<queue>using namespace std;struct node{ int next,to,t,u; long long c;}a[2000010],f[1000010];int n,m,s,tot,d,tt,fa[500010],first[500010];long long dis[500010];bool flag[500010];inline int read(){ int i=0;char c; for(c=getchar();c<'0'||c>'9';c=getchar()); for(;c>='0'&&c<='9';c=getchar()) i=(i<<1)+(i<<3)+c-'0'; return i;}inline void add(int x,int y,long long w,long long aa){ a[++tot].next=first[x]; first[x]=tot; a[tot].to=y; a[tot].t=w; a[tot].u=x; a[tot].c=aa*w;}inline int gf(int x){ if(fa[x]!=x) fa[x]=gf(fa[x]); return fa[x];}inline void dfs(){ for(int i=1;i<=m;i++) { int fx=gf(f[i].u),fy=gf(f[i].to); if(fx!=fy) { fa[fy]=fx; d=f[i].t; } if(gf(s)==gf(tt)) break; }}inline void zql(int s){ priority_queue<pair<long long,int> >q; memset(dis,127,sizeof(dis)); dis[s]=0; q.push(make_pair(0,s)); while(!q.empty()) { pair<long long,int>now=q.top(); q.pop(); if(now.second==tt) break; if(flag[now.second]) continue; flag[now.second]=1; for(int p=first[now.second];p;p=a[p].next) if(!flag[a[p].to]&&dis[a[p].to]>dis[now.second]+a[p].c) { dis[a[p].to]=dis[now.second]+a[p].c; q.push(make_pair(-dis[a[p].to],a[p].to)); } }}inline bool comp(node a,node b){ return a.t<b.t;}int main(){ freopen("running.in","r",stdin); freopen("running.out","w",stdout); n=read(),m=read(); for(int i=1;i<=m;i++) { f[i].u=read(); fa[f[i].u]=f[i].u; f[i].to=read(); fa[f[i].to]=f[i].to; f[i].t=read(); f[i].next=read(); } sort(f+1,f+m+1,comp); s=read(),tt=read(); dfs(); for(int i=1;i<=m;i++) if(f[i].t<=d) { add(f[i].u,f[i].to,f[i].t,f[i].next); add(f[i].to,f[i].u,f[i].t,f[i].next); } else break; zql(s); printf("%d %lld\n",d,dis[tt]); return 0;}
3.大逃杀
地图上有n个点,由n-1条无向边连接,保证连通,通过每一条边需要花费一定的时间。
有些点上有资源,获取资源可以增强武力值wi,可以选择不获取;有些点上有敌人,需要花费ti的时间杀死敌人,不能无视敌人,武力值和杀死敌人的时间没有关系。
若某个点上既有资源又有敌人,必须先杀了敌人再拿资源。获取资源不需要时间。
总时间为T,希望时间结束前武力值尽量大。
输入格式
第一行n和T,代表点数和时间。
第二行n个整数为wi。
第三行n个整数为ti。
接下来n-1行,每行三个整数a,b,c代表通过连接a和b的双向道路所花时间为C。
输出格式
一个整数代表最大武力值。
输入样例
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
这道题。。怎么说呢。。。好吧我真的没有往树型DP的方向去想。
不过WKL凯爷的分析很有道理,求子树的时候,大部分都用了树型DP。
开一个三维数组f[i][j][3],状态转移的时候只需要dfs一遍。
f[i][j][0]代表进入以i为根的子树并回到i;
f[i][j][1]代表进入以i为根的子树并不回到i;
f[i][j][2]代表从以i为根的子树内出发,经过i并回到以i为根的子树内;
用j秒能得到的最大武力值。
更新的时候用i的一个儿子从大到小枚举j更新i的答案。
答案是所有子树的最大值。
唔。。。用一下别人的代码。。这个状态转移异常的容易写错。。。
@g19zjj
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<vector>#include<queue>#define ll long longusing namespace std;int getint(){ int i=0,f=1;char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-')f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f;}const int N=305;int n,T,val[N],t[N],f[N][N][3],tmp[N];int tot,first[N],nxt[N<<1],to[N<<1],w[N<<1];void add(int x,int y,int z){ nxt[++tot]=first[x],first[x]=tot,to[tot]=y,w[tot]=z;}void dfs(int u,int fa){ int i,j; for(int i=t[u];i<=T;i++) f[u][i][0]=f[u][i][1]=f[u][i][2]=val[u]; for(int e=first[u];e;e=nxt[e]) { int v=to[e]; if(v==fa)continue; dfs(v,u); for(i=0;i<=T;i++)tmp[i]=f[u][i][2]; for(j=0;j<=T;j++) { for(i=2*w[e]+j+t[u];i<=T;i++) tmp[i]=max(tmp[i],f[u][i-2*w[e]-j][2]+f[v][j][0]); for(i=2*w[e]+j+t[u];i<=T;i++) tmp[i]=max(tmp[i],f[u][i-2*w[e]-j][0]+f[v][j][2]); for(i=w[e]+j+t[u];i<=T;i++) tmp[i]=max(tmp[i],f[u][i-w[e]-j][1]+f[v][j][1]); } for(i=0;i<=T;i++)f[u][i][2]=tmp[i]; for(i=0;i<=T;i++)tmp[i]=f[u][i][1]; for(j=0;j<=T;j++) { for(i=2*w[e]+j+t[u];i<=T;i++) tmp[i]=max(tmp[i],f[u][i-2*w[e]-j][1]+f[v][j][0]); for(i=w[e]+j+t[u];i<=T;i++) tmp[i]=max(tmp[i],f[u][i-w[e]-j][0]+f[v][j][1]); } for(i=0;i<=T;i++)f[u][i][1]=tmp[i]; for(i=0;i<=T;i++)tmp[i]=f[u][i][0]; for(j=0;j<=T;j++) for(i=2*w[e]+j+t[u];i<=T;i++) tmp[i]=max(tmp[i],f[u][i-2*w[e]-j][0]+f[v][j][0]); for(i=0;i<=T;i++)f[u][i][0]=tmp[i]; }}int main(){ //freopen("lx.in","r",stdin); //freopen("toyuq.out","w",stdout); int x,y,z; n=getint(),T=getint(); for(int i=1;i<=n;i++)val[i]=getint(); for(int i=1;i<=n;i++)t[i]=getint(); for(int i=1;i<n;i++) { x=getint(),y=getint(),z=getint(); add(x,y,z),add(y,x,z); } dfs(1,0); int ans=0; for(int i=1;i<=n;i++) for(int j=0;j<=T;j++) for(int k=0;k<3;k++) ans=max(ans,f[i][j][k]); cout<<ans;}
没有然后了。
来自2017.10.26.
——我认为return 0,是一个时代的终结。
- 10月集训test13
- Test13
- test13
- test13
- 10月集训test3
- 10月集训test4
- 10月集训test5
- 10月集训test6
- 10月集训test7
- 10月集训test8
- 10月集训test9
- 10月集训test10
- 10月集训test11
- 10月集训test12
- 10月集训test14
- 10月集训test15
- 10月集训test16
- 10月集训test20
- 数组,集合的创建及赋值方式
- Java代码实现负载均衡五种算法
- Android Utils工具类集合
- 关于canvas画布使用fillRect()时高度会放大的解决方案
- 高数 01.02数列的极限
- 10月集训test13
- 字符串和for的理解
- tensorflow--数据读取篇
- [NOIP2017模拟]做运动
- mysql(3):mysql与java的连接使用
- PyTorch参数初始化方法
- 无聊的switch题,神奇的小想法
- Pytorch模块-argparse
- 二周第四次课 2017.10.26 set_uid、set_gid、stick_bit、软链接、硬连接