终于不是地主家的傻儿子企鹅豆豆了。。。
今天是运动会的第一天,锣鼓喧天,热闹非凡。。。而我在考试。。
呵呵。
然而还是感谢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
关于这道题,真的不知道应该说什么。。。。。。
其实可能并不难。。吧。。毕竟连出题的人都没有考虑全所有情况,题解都是错的,但是对于这道题的数据来说足够了。
嗯,长度不一样不能换,非小写字母为不一样不能换,同一小写字母对的不一样不能换。
但是还是少了可能性:
abcdefghijklmnopqrstuvwxyz
zyxwvutsrqponmlkjihgfedcba
这样应该是换不了的。(不过鉴于数据干脆就不考虑了吧。)
#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 long
using 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,是一个时代的终结。