版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/84635750
解题报告
洛谷 1518 两只塔姆沃斯牛 The Tamworth Two
分析
同时模拟牛和FJ的行为判断即可
代码
/*
ID:lemondi1
LANG:C++
TASK:ttwo
*/
#include <cstdio>
#define rr register
using namespace std;
struct site{int x,y,dir;}cow,john;
const int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
char s[12][12]; int ans,v[11][11][11][11];
signed main(){
freopen("ttwo.in","r",stdin);
freopen("ttwo.out","w",stdout);
for (rr int i=1;i<11;++i) scanf("%s",s[i]+1);
for (rr int i=0;i<12;++i) s[0][i]=s[11][i]=42;
for (rr int i=1;i<11;++i) s[i][0]=s[i][11]=42;
for (rr int i=1;i<11;++i)
for (rr int j=1;j<11;++j)
if (s[i][j]=='C') cow=(site){i,j,0};
else if (s[i][j]=='F') john=(site){i,j,0};
while (cow.x!=john.x||cow.y!=john.y){
if (++v[cow.x][cow.y][john.x][john.y]==5) return !printf("0\n"); ++ans;
if (s[cow.x+dx[cow.dir]][cow.y+dy[cow.dir]]==42) cow.dir=(cow.dir+1)%4; else cow.x+=dx[cow.dir],cow.y+=dy[cow.dir];
if (s[john.x+dx[john.dir]][john.y+dy[john.dir]]==42) john.dir=(john.dir+1)%4; else john.x+=dx[john.dir],john.y+=dy[john.dir];
}
return !printf("%d\n",ans);
}
洛谷 1519 穿越栅栏 Overfencing
题目
问迷宫内的点到两个出口的最长的最短路
分析
一个一个肯定会超时,于是可以在两个出口进行深搜或者广搜,求出最长的答案,虽然讲得好像很简单,但是对于奇葩数据简直就是撞墙,关键是输入比较坑
代码
/*
ID:lemondi1
LANG:C++
TASK:maze1
*/
#include <cstdio>
#include <queue>
#define rr register
using namespace std;
const int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
struct node{int x,y,w;}; queue<node>q;
int n,m,ans; bool v[111][51][4],vis[111][51];
signed main(){
freopen("maze1.in","r",stdin);
freopen("maze1.out","w",stdout);
scanf("%d%d",&m,&n);
rr char c=getchar();
while (c=='\r'||c=='\n') c=getchar();
for (rr int i=1;i<2*n+2;++i)//处理输入的边,难度比较大
if (i&1){
while (c!='+') c=getchar();
for (rr int j=1;j<=m;++j)
v[i>>1][j][2]=v[(i+1)>>1][j][0]=getchar()==' ',
getchar();
getchar();
}
else{
c=getchar();
while (c=='\r'||c=='\n') c=getchar();
for (rr int j=1;j<=m;++j)
v[i>>1][j-1][1]=v[i>>1][j][3]=c==' ',
getchar(),c=getchar();
v[i>>1][m][1]=v[i>>1][m+1][3]=c==' ';
while (c!='\r'&&c!='\n') c=getchar();
}
for (rr int i=1;i<=n;++i){//处理两个出口的位置
if (v[i][1][3]) q.push((node){i,1,1}),vis[i][1]=1;
if (v[i][m][1]) q.push((node){i,m,1}),vis[i][m]=1;
}
for (rr int i=2;i<m;++i){
if (v[1][i][0]) q.push((node){1,i,1}),vis[1][i]=1;
if (v[n][i][2]) q.push((node){n,i,1}),vis[n][i]=1;
}
while (q.size()){//普通的广搜
rr int x=q.front().x,y=q.front().y,w=q.front().w;
q.pop(); ans=ans>w?ans:w;
for (rr int k=0;k<4;++k)
if (v[x][y][k]){
rr int rx=x+dx[k],ry=y+dy[k];
if (vis[rx][ry]||rx<1||ry<1||rx>n||ry>m) continue;//要判断边界!
q.push((node){rx,ry,w+1}); vis[rx][ry]=1;
}
}
printf("%d\n",ans);
return 0;
}
洛谷 1522 牛的旅行 Cow Tours
题目
加入一条连接两个连通块的边,使两个连通块之间的点的最长路径最小
分析
首先可以先跑一次floyd,求出每个连通块内部的最短距离,然后依次访问没有加入的边,求出最小值,并与原先的最大结果做比较
代码
/*
ID:lemondi1
LANG:C++
TASK:cowtour
*/
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#define w(t) ((t)*(t))
#define count(i,j) sqrt(w(x[i]-x[j])+w(y[i]-y[j]))
#define rr register
using namespace std;
int n,x[151],y[151]; double dis[151][151],maxx[151],ans;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
return ans;
}
inline double min(double a,double b){return a<b?a:b;}
signed main(){
freopen("cowtour.in","r",stdin);
freopen("cowtour.out","w",stdout);
n=iut(); memset(dis,0x6f,sizeof(dis));
for (rr int i=1;i<=n;++i) x[i]=iut(),y[i]=iut(),dis[i][i]=0;
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j){
rr char c=getchar();
while (c!=48&&c!=49) c=getchar();
if (c==49) dis[i][j]=count(i,j);
}
for (rr int k=1;k<=n;++k)//floyd
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
for (rr int i=1;i<=n;++i)//找出连接i点的最长路径
for (rr int j=1;j<=n;++j)
if (dis[i][j]!=dis[0][1])
maxx[i]=maxx[i]>dis[i][j]?maxx[i]:dis[i][j];
for (rr int i=1;i<=n;++i) ans=ans>maxx[i]?ans:maxx[i];//先求一遍最大值
rr double ans1=dis[0][1];
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j)
if (dis[i][j]==dis[0][1])//当可以连接两个连通块时
ans1=min(ans1,maxx[i]+count(i,j)+maxx[j]);//求最小值
printf("%.6lf\n",ans>ans1?ans:ans1);
return 0;
}
洛谷 1529 回家 Bessie Come Home
题目
裸的最短路
代码(dijkstra+堆优化)
/*
ID:lemondi1
LANG:C++
TASK:comehome
*/
#include <cstdio>
#include <queue>
using namespace std;
struct node{
int y,w,next;
}e[20011];
struct rec{
int x,d;
bool operator <(const rec &t)const{
return d<t.d;
}
};
int m,n,k=1,dis[61],ls[61],vis[2001];
char ans=65; priority_queue<rec>q;
int main(){
freopen("comehome.in","r",stdin);
freopen("comehome.out","w",stdout);
scanf("%d\n",&m);
for (int i=1;i<=m;++i){
char x,y; int w;
scanf("%c %c %d\n",&x,&y,&w);
if (!vis[x]) vis[x]=++n;
if (!vis[y]) vis[y]=++n;
e[++k]=(node){vis[y],w,ls[vis[x]]}; ls[vis[x]]=k;
e[++k]=(node){vis[x],w,ls[vis[y]]}; ls[vis[y]]=k;
}
for (int i=0;i<=n;++i) dis[i]=707406378;
q.push((rec){vis['Z'],0}); dis[vis['Z']]=0;
while (q.size()){
int x=q.top().x,d=q.top().d; q.pop();
if (dis[x]!=d) continue;
for (int i=ls[x];i;i=e[i].next)
if (dis[x]+e[i].w<dis[e[i].y]){
dis[e[i].y]=dis[x]+e[i].w;
q.push((rec){e[i].y,dis[e[i].y]});
}
}
for (char i='B';i<'Z';++i)
if (dis[vis[i]]<dis[vis[ans]]) ans=i;
printf("%c %d\n",ans,dis[vis[ans]]);
return 0;
}
洛谷 1530 分数化小数 Fractions to Decimals
后续
没有后续