目录
- A 七七七七(水题)
- B 平面旅行(枚举)
- C 小球下落(dfs暴力)
- D 自由世界(spfa打脸正解)
A 七七七七
题目
链接
来源:牛客网
牛牛最近对7很感兴趣,他想到了一个问题。
牛牛想存n元钱,他决定第1天存1元,第2天存7元,第3天存49元,以此类推,每天存的钱是前一天的7倍。
牛牛想知道几天后,存款的总额能大于等于n元钱。
不会吧不会吧,这都不会
思路
被我吃了
直接暴力
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<iomanip>
using namespace std;
int main()
{
int n;
cin>>n;
unsigned long long s=0,k=1,i=0;
while (s<n)
{
s+=k;
i++;
k*=7;
}
cout<<i<<endl;
return 0;
}
B 平面旅行
题目
链接
来源:牛客网
牛牛最近在玩某款游戏,其地图可以看成一个平面直角坐标系。
地图上存在n个小镇,小镇从1到n编号。第i个小镇的坐标为(x_i,y_i)。定义两个小镇的距离为曼哈顿距离,比如小镇i到小镇j的距离为∣xi−xj∣+∣yi−yj∣,其中,|a|表示取a的绝对值。
牛牛在m个小镇建立了传送门,也就是说,牛牛可以在任何时候任何瞬间不花费任何代价,直接到达这m个小镇的任何一个。
牛牛一开始在小镇1,牛牛想按1到n的顺序访问所有小镇按顺序做任务,问牛牛需要走过的最短距离是多少。
牛牛可以提前到达某个小镇,但是必须做完前一个小镇的任务,才能做下一个小镇的任务。做任务本身不会增加距离。
范围
对于20%的数据有m=0。
对于40%的数据有m=1。
对于60%的数据有n,m≤300。
对于100%的数据有1≤n≤5000,0≤m≤n,−10000≤xi,yi≤10000。
思路
可以发现对于每一个有传送门的点都不用处理,而每一个没有传送门的点都由一个有传送门的点或上一个点步行过去(自己证)
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
struct f{
int x,y;
} f[5001];
int op[5001];
long long a;
bool book[5001];
long long o(int x,int y,int x2,int y2)
{
return abs(x-x2)+abs(y-y2);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&f[i].x,&f[i].y);
}
int x;
unsigned long long s=0;
for (int i=1;i<=m;i++)
{
scanf("%d",&x);
op[i]=x;
book[x]=1;
}
for (int i=1;i<n;i++)
{
if (book[i+1]) continue;
a=o(f[i].x,f[i].y,f[i+1].x,f[i+1].y);
for (int j=1;j<=m;j++)
{
a=min(a,o(f[i+1].x,f[i+1].y,f[op[j]].x,f[op[j]].y));
}
s+=a;
}
cout<<s<<endl;
return 0;
}
C 小球下落
题目
链接
来源:牛客网
有一块大小为n行2列的板子,每个位置可能是一个小球,用’o’表示,可能是障碍物,用’x’表示,也可能空无一物,用’.'来表示。
每个小球可以向左向右或者向下移动,但是不能向上移动,或者和某个小球重叠,也不能越出板子。
每个小球向下移动一个单位,牛牛可以获得一分。
牛牛想知道对于某个开始状态,能得到的最大分数是多少。
范围
对于20%的数据有n≤3。
另有20%的数据k≤10。
对于60%的数据有n≤1000。
对于100%的数据有1≤n≤300000。
思路
如此人才的一道题目怎么能不暴力呢??
纯种暴力,不添加任何优化,坚持在原产地鲜榨
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n;
char a[300001][2];
int s=0;
int dfs(int x,int y,int dep)
{
if (x==n) return dep;
if (a[x+1][y]!='.'&&(a[x+1][1-y]!='.'||a[x][1-y]!='.'))
{
return dep;
}
int xx=0;
if (a[x+1][0]=='.') xx=dfs(x+1,0,dep+1);
if (a[x+1][1]=='.') xx=max(dfs(x+1,1,dep+1),xx);
return xx;
}
int main()
{
int n;
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
cin>>a[i];
}
for (int i=n;i>=1;i--)
{
if (a[i][0]=='o')
{
a[i][0]='.';
int x=dfs(i,0,0);
s+=x;
x+=i;
if (a[x][1]=='.'&&a[x][0]=='.')
{
if (a[x-1][0]=='x') a[x][0]='o';
else a[x][1]='o';
}
else
{
if (a[x][1]=='.') a[x][1]='o';
else
{
a[x][0]='o';
}
}
}
if (a[i][1]=='o')
{
a[i][1]='.';
int x=dfs(i,1,0);
s+=x;
x+=i;
if (a[x][1]=='.'&&a[x][0]=='.')
{
if (a[x-1][0]=='x') a[x][0]='o';
else a[x][1]='o';
}
else
{
if (a[x][1]=='.') a[x][1]='o';
else
{
a[x][0]='o';
}
}
}
if (a[i][0]=='o')
{
a[i][0]='.';
int x=dfs(i,0,0);
s+=x;
x+=i;
if (a[x][1]=='.'&&a[x][0]=='.')
{
if (a[x-1][0]=='x') a[x][0]='o';
else a[x][1]='o';
}
else
{
if (a[x][1]=='.') a[x][1]='o';
else
{
a[x][0]='o';
}
}
}
}
cout<<s<<endl;
return 0;
}
D 自由世界
题目
链接
来源:牛客网
牛牛最近在玩某款游戏,其地图不能看成一个平面直角坐标系,而类似于一张无向图。
地图上存在n个小镇,小镇从1到n编号。有m条道路连接两个小镇,每条道路有其长度w_i。
牛牛在k个小镇建立了传送门,也就是说,牛牛可以在任何时候任何瞬间不花费任何代价,直接到达这k个小镇的任何一个。
牛牛一开始在小镇1,牛牛想按1到n的顺序访问所有小镇按顺序做任务,问牛牛需要走过的最短长度是多少。
牛牛可以提前到达某个小镇,但是必须做完前一个小镇的任务,才能做下一个小镇的任务。做任务本身不会增加长度。
范围
对于10%的数据有n≤3,k=0。
对于30%的数据有k=0。
另有30%的数据有m=n-1。
对于60%的数据有n≤300。
对于100%的数据有1≤n≤2000,n−1≤m≤5000,0≤k≤n,1≤ui,vi≤n,1≤wi≤1000。
数据保证给定的小镇两两相互可达。
注意,连接某两个小镇的可能有多条道路,也有可能有道路的两端是同一个小镇。
思路
虽然正解是dij,但是……(我绝不会告诉你们我是spfa过的,而且机房巨佬犯罪嫌疑人lyf68ms的spfa在10.30还是最优解)
首先可以把也有可能有道路的两端是同一个小镇 的这种乡村风景观光旅行边给去掉,然后,我们的任意门小镇可以直接进入spfa的队列中(反正做了第一次以后都要进去的),就不用多建边了.
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int head[2001],d[2001],n,m,k,tot=1;
queue<int> q;
struct f{
int to,next,w;
} b[10001];
bool book[2001];
void add(int x,int y,int z)
{
b[tot].to=y;
b[tot].w=z;
b[tot].next=head[x];
head[x]=tot;
tot++;
}
void spfa(int x)
{
q.push(x);
for (int i=1;i<=n;i++)
{
if (book[i]) d[i]=0,q.push(i);
else d[i]=2000*1000+20;
}
d[x]=0;
while (q.size())
{
int xx=q.front();
q.pop();
for (int i=head[xx];i;i=b[i].next)
{
if (d[b[i].to]>d[xx]+b[i].w)
{
d[b[i].to]=d[xx]+b[i].w;
q.push(b[i].to);
}
}
}
}
int main()
{
cin>>n>>m>>k;
for (int i=0;i<m;i++)
{
int x,y,z;
cin>>x>>y>>z;
if (x==y) continue;
add(x,y,z);
add(y,x,z);
}
for (int i=0;i<k;i++)
{
int x;
cin>>x;
book[x]=1;
}
long long s=0;
for (int i=1;i<n;i++)
{
if (book[i+1]) continue;
spfa(i);
s+=d[i+1];
}
cout<<s<<endl;
return 0;
}