2018.07.04测试
说在前边
yeah我回来了(虽然过几天又要走了)
我105的C币怎么只有15个了啊
樱樱樱
樱樱樱
路径
时间限制: 1 Sec 内存限制: 128 MB
题目描述
有n个点,m条无向边,有A,B两个人,初始时刻A在点1,B在点2,他们要走到点n去。A每走一条边,要消耗B单位能量,B每走一条边,要消耗E单位能量。如果A,B相伴走,则只消耗P单位的能量。请问A,B走到点n,最少要消耗多少能量?
输入数据保证1和n,2和n连通。
输入
输入:第一行包含整数B,E,P,N和M,所有的整数都不超过40000,N>=3.
接下来M行,每行两个整数,表示该无向边连接的两个顶点。
输出
一个整数,表示最小要消耗的能量
样例输入
4 4 5 8 8
1 4
2 3
3 4
4 7
2 5
5 6
6 8
7 8
样例输出
22
分析
考试的时候没有任何头绪。
我不看足球了!!!!!
根本没有睡醒好咩?!!?!??!
如果这么看就好了。
两人分别从1,2点出发,在图上某一点会合。
会合前,两人每走一条边会有不同的能量消耗,会合后,两人一起,能量消耗又会变化。
而求最小消耗的话,会合之前,两人都要走最短路径,会合之后,两人也要走最短路径。
所以在哪个点会合呢?
枚举一下就Ok了。
判断的方法:用
1到这里的最短距离*A的消耗+2到这里的最短距离*B的消耗+n到这里的最短距离*AB合体后的消耗
取最小值即可。
这样的话,边权都是1,可以开开心心地跑bfs了。
代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
void Read(int &p)
{
p=0;
char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9')
p=p*10+c-'0',c=getchar();
}
const int MX=40000+4;
const int XM=80000+4;
int n,m,a,b,ab,p,q;
int to[XM],nxt[XM],head[MX],cnt,dis[3][MX];
void addedge(int p,int q)
{
to[++cnt]=q,nxt[cnt]=head[p],head[p]=cnt;
to[++cnt]=p,nxt[cnt]=head[q],head[q]=cnt;
}
queue<int>Q;
bool vis[MX];
void bfs(int grandorder)
{
memset(vis,0,sizeof vis);
while(!Q.empty()) Q.pop();
int s=(grandorder==2)?n:grandorder+1;
dis[grandorder][s]=0, Q.push(s), vis[s]=1;
while(!Q.empty())
{
int h=Q.front(); Q.pop();
for(int i=head[h];i;i=nxt[i])
if(!vis[to[i]])
Q.push(to[i]),vis[to[i]]=1,
dis[grandorder][to[i]]=dis[grandorder][h]+1;
}
}
int main()
{
Read(a); Read(b); Read(ab);Read(n); Read(m);
for(int i=1;i<=m;i++)
Read(p),Read(q),addedge(p,q);
memset(dis,120,sizeof dis);
bfs(0); bfs(1); bfs(2);
int ans=2147483647;
for(int i=1;i<=n;i++) ans=min(ans,dis[0][i]*a+dis[1][i]*b+dis[2][i]*ab);
printf("%d\n",ans);
}
闲得……dant……发慌码了一个手动队列……
(其实是我某处做错了怀疑是queue的问题樱樱樱)
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
void Read(int &p)
{
p=0;
char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9')
p=p*10+c-'0',c=getchar();
}
const int MX=40000+4;
const int XM=80000+4;
int n,m,a,b,ab,p,q;
int to[XM],nxt[XM],head[MX],cnt,dis[3][MX];
void addedge(int p,int q)
{
to[++cnt]=q,nxt[cnt]=head[p],head[p]=cnt;
to[++cnt]=p,nxt[cnt]=head[q],head[q]=cnt;
}
int fakeq[MX],he,ta;
bool vis[MX];
void bfs(int grandorder)
{
memset(vis,0,sizeof vis);
he=ta=0;
int s=(grandorder==2)?n:grandorder+1;
dis[grandorder][s]=0,fakeq[ta++]=s,vis[s]=1;
while(he<ta)
{
int h=fakeq[he++];
for(int i=head[h];i;i=nxt[i])
if(!vis[to[i]])
fakeq[ta++]=to[i],
dis[grandorder][to[i]]=dis[grandorder][h]+1,
vis[to[i]]=1;
}
}
int main()
{
Read(a); Read(b); Read(ab);Read(n); Read(m);
for(int i=1;i<=m;i++)
Read(p),Read(q),addedge(p,q);
memset(dis,120,sizeof dis);
bfs(0); bfs(1); bfs(2);
int ans=2147483647;
for(int i=1;i<=n;i++) ans=min(ans,dis[0][i]*a+dis[1][i]*b+dis[2][i]*ab);
printf("%d\n",ans);
}
魔法(magic)
题目描述
小魔仙为了拯救她的好朋友芭比兔,千方百计的弄到了关押芭比兔的迷宫的地图。迷宫的入口在点1处,关押芭比兔的地点在点n处。在迷宫中,小魔仙只能沿着水平方向或竖直方向移动,否则就会碰壁。迷宫中的墙是无形的,幸好地图中已经给出了小魔仙的所有必经地点,她必须严格按照地图中给出的顺序访问这些必经点,才能达到点n处。小魔仙走路的速度很慢,每秒种只能走一个单位距离。但是小魔仙可以施展魔法,这样她可以瞬间跳过其中若干点,时间消耗几乎为0。但是她的魔法最多只能让她跳过k个点(注意:她不能跳过起点和终点,即点1和点n)。她想以最快的速度救出芭比兔,请问她最少需要多少时间。地图的行经路线可能会多次经过同一个坐标。小魔仙跳过的k个点是指在行经路线中的点,如果某个点被跳过多次,则每一次都要消耗魔法。(3<=n<=500)
输入
第一行包含N,K.接下来N行包含两个整数x,y,表示需要访问的顶点坐标。(-1000<=x<=1000,-1000<=y<=1000).
输出
小魔仙最少需要的时间。
输入样例
5 2
0 0
8 3
1 1
10 -5
2 2
输出样例
4
样例解释
小魔仙可以跳过(8,3),(10,-5)。
数据规模与约定(手动加的)
N,K不超过500
分析
不知道为什么一眼就看出来是一个选或不选的01背包问题^-^。
考试的时候就分析了这么个方程:
dp[i][j]表示到第i个点的时候用了j次魔法
如果到这里来的时候没用魔法
则dp[i][j]=dp[i-1][j]+dis[i][i-1]
如果从上一个点到这里来时用了魔法
则dp[i][j]=dp[i-2][j-1]+dis[i][i-2]
只得了12分的说(╥╯^╰╥)
为什么错了呢?
“如果从上一个点到这里来时用了魔法”
我好像不知道有多段跳似的,,,
如果有8个点,6个魔法,我们不可以直接刷刷刷刷刷刷跳到终点么?这样就是上六个点。
因此,我们应该枚举一下到底是上几个点跳过来的。
具体的方程请详见代码。
代码
#include<cmath>
#include<cstdio>
#include<cstring>
void Read(int &p)
{
p=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
p=p*10+c-'0',c=getchar();
p*=f;
}
const int MX=500+4;
int n,k,x[MX],y[MX],dis[MX][MX],dp[MX][MX];
int Xbs(int i){return i>=0?i:-i;}
int mn(int a,int b){return a<b?a:b;}
int main()
{
Read(n); Read(k);
for(int i=1;i<=n;i++)
Read(x[i]),Read(y[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=Xbs(x[i]-x[j])+Xbs(y[i]-y[j]);
memset(dp,120,sizeof dp);
for(int j=0;j<=k;j++) dp[1][j]=0;
for(int i=2;i<=n;i++)
for(int j=k;j>=0;j--)
for(int l=0;l<=j;l++)
dp[i][j]=mn(dp[i][j],dp[i-l-1][j-l]+dis[i][i-1-l]);
int ans=2147483647;
for(int j=0;j<=k;j++) ans=mn(ans,dp[n][j]);
printf("%d\n",ans);
}
公路
时间限制: 1 Sec 内存限制: 128 MB
题目描述
有一条单向的高速公路,只有一条车道,有n(1<=n<=100000)辆车在车高速路上行驶。他们的车速可能不同。但因为只有一条车道,所以不存在超车的可能。如果一辆车追上了前车,它就只能减速,与前车以同样的速度行驶,这样它们可以成为一个group。这些汽车的体积可以忽略不计。问经过T单位时间,高速公路上一共有多少个group。(当T时刻时,所有位置相同的汽车称为一个group)。
输入
输入格式:第一行两个整数N,T(1<=T<=1000000000)。
接下来N行,每行包含两个整数,分别表示一辆车的初始位置和初始速度
输出
一个整数,表示T时刻后有多少个group。
样例输入
5 3
0 1
1 2
2 3
3 2
6 1
样例输出
3
分析
一年多以前做过一遍,考试一拿到就想出来了……
……
……
……
一种不一样的方法。
题意比较好懂,想象一下那个场景就OK了。
追上了但因为路……窄而只能合体一起走,就成了一个group,大家都变得慢悠悠
所以
我们只需要看哪些本来落后的车追上了前面的车即可
所以:
因为输出不会按顺序给你谁先谁落后,我们要先按起始位置排序
怎样知道能否追上?
1、相同时间比路程:算出两辆车T时刻时所处位置(如果没有group这种设定)
2、比时间:算出追及的时间看在不在T时刻内
然后就从1开始,看1能不能追上2,2能不能追上3……
这么想的话,恭喜您获得了6分!(坏笑)
如果是这样你就要被扣很多分了哟,你还有比完2和3之后,再来比较1和2
怎么解决?
因为无论是谁先追上谁,反正最终是追上了,而group的领头羊无论如何都会被它身后离它最近的车追上
所以倒着搞就没问题了
代码
方法一:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define lol long long
void Read(lol &p)
{
p=0;
char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9')
p=p*10+c-'0',c=getchar();
}
const int MX=100000+5;
lol T,n,groups;
struct cars
{
lol v,p,final;
void R()
{
Read(p); Read(v); final=p+v*T;
}
bool operator < (const cars &a) const
{
return p>a.p;
}
}c[MX];
int main()
{
Read(n); Read(T); groups=n;
for(lol i=1;i<=n;i++) c[i].R();
sort(c+1,c+1+n);
lol locating=c[1].final;
for(lol i=2;i<=n;i++)
if(locating<=c[i].final) groups--;
else locating=c[i].final;
cout<<groups<<endl;
}
方法二:
羞)我说的一年前的那种不同的方法
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=102017;
void Read(LL & p)
{
p=0;
char c=getchar();
while(c<'0' or c>'9') c=getchar();
while(c>='0' and c<='9')
p=p*10+c-'0',c=getchar();
}
struct Epic
{
LL v,s;
bool operator < (const Epic & p) const
{
return s<p.s;
}
}car[maxn];
LL T,n,ans;
LL took(LL i,LL j)
{
return (car[j].s-car[i].s)/(car[i].v-car[j].v);
}
int main ()
{
Read(n); Read(T);
ans=n;
for(LL i=1;i<=n;i++)
Read(car[i].s),Read(car[i].v);
sort(car+1,car+1+n);
for(LL i=1;i<=n;i++)
for(LL j=i+1;j<=n;j++)
if(car[i].s==car[j].s)
{
ans--;
break;
}
else if(car[i].v>car[j].v)
{
if(took(i,j)<=T)
{
ans--;
break;
}
}
printf("%lld\n",ans);
}