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,是一个时代的终结。

原创粉丝点击