您的位置:首页 > 其它

jzoj_1月27日D组

2018-01-28 19:04 134 查看

第一题(反射)

题意:

    给出一些镜子,有摆成'/'和'\'样子的,求一个光源照进来最多会在这些镜子中反射几次。

思路:

    光射进来有四个方向,我们可以设置一个变量记录方向状态,然后从四个方向来枚举并保存最大值,一开始我就是这样做的,然后因为一个细节浪费了很多时间。

代码:

#include<cstdio>
#include<cstring>
int fx,x,y,n,m,ans,s;//fx记录方向状态,从左射来是1,右是2,上是3,下是4
char c[1001][1001];
int max(int x,int y){return x>y?x:y;}
int main()
{
freopen("mirror.in","r",stdin);
freopen("mirror.out","w",stdout);
scanf("%d%d",&n,&m);
getchar();
for (int i=1;i<=n;i++,getchar())
for (int j=1;j<=m;j++)
c[i][j]=getchar();
for (int i=1;i<=n;i++)
{
x=i;y=1;fx=1;//这里是从左边射来枚举
while (x>=1&&x<=n&&y>=1&&y<=m)
{
if (c[x][y]=='/'&&fx==1) x--,fx=4;//如果从左射'/'会改变方向到上面,坐标也会改变
else if (c[x][y]=='/'&&fx==2) x++,fx=3;//右射'/'会改变方向到下面
else if (c[x][y]=='/'&&fx==3) y--,fx=2;//上射'/'会改变方向到左边
else if (c[x][y]=='/'&&fx==4) y++,fx=1;//下射'/'会改变方向到右边
else if (c[x][y]!='/'&&fx==1) x++,fx=3;//左射'\'会改变方向到下面
else if (c[x][y]!='/'&&fx==2) x--,fx=4;//右射'\'会改变方向到上面
else if (c[x][y]!='/'&&fx==3) y++,fx=1;//上射'\'会改变方向到右边
else if (c[x][y]!='/'&&fx==4) y--,fx=2;//下射'\'会改变方向到左边
s++;
}
ans=max(ans,s);
s=0;
x=i;y=m;fx=2;//右边
while (x>=1&&x<=n&&y>=1&&y<=m)
{
if (c[x][y]=='/'&&fx==1) x--,fx=4;
else if (c[x][y]=='/'&&fx==2) x++,fx=3;
else if (c[x][y]=='/'&&fx==3) y--,fx=2;
else if (c[x][y]=='/'&&fx==4) y++,fx=1;
else if (c[x][y]!='/'&&fx==1) x++,fx=3;
else if (c[x][y]!='/'&&fx==2) x--,fx=4;
else if (c[x][y]!='/'&&fx==3) y++,fx=1;
else if (c[x][y]!='/'&&fx==4) y--,fx=2;
s++;
}
ans=max(ans,s);
s=0;
}
for (int i=1;i<=m;i++)
{
x=1;y=i;fx=3;//上面
while (x>=1&&x<=n&&y>=1&&y<=m)
{
if (c[x][y]=='/'&&fx==1) x--,fx=4;
else if (c[x][y]=='/'&&fx==2) x++,fx=3;
else if (c[x][y]=='/'&&fx==3) y--,fx=2;
else if (c[x][y]=='/'&&fx==4) y++,fx=1;
else if (c[x][y]!='/'&&fx==1) x++,fx=3;
else if (c[x][y]!='/'&&fx==2) x--,fx=4;
else if (c[x][y]!='/'&&fx==3) y++,fx=1;
else if (c[x][y]!='/'&&fx==4) y--,fx=2;
s++;
}
ans=max(ans,s);
s=0;
x=n;y=i;fx=4;//下面
while (x>=1&&x<=n&&y>=1&&y<=m)
{
if (c[x][y]=='/'&&fx==1) x--,fx=4;
else if (c[x][y]=='/'&&fx==2) x++,fx=3;
else if (c[x][y]=='/'&&fx==3) y--,fx=2;
else if (c[x][y]=='/'&&fx==4) y++,fx=1;
else if (c[x][y]!='/'&&fx==1) x++,fx=3;
else if (c[x][y]!='/'&&fx=
4000
=2) x--,fx=4;
else if (c[x][y]!='/'&&fx==3) y++,fx=1;
else if (c[x][y]!='/'&&fx==4) y--,fx=2;
s++;
}
ans=max(ans,s);
s=0;
}
printf("%d",ans);
}

第三题(道路阻塞)

题意:

    求一个图的最短路径,我们在任意一条边中放置障碍物,可以使那条边变成原来的两倍,我们要求把障碍物放到任意一条边,可以使这个图的最短路径和之前最短路径的差最大。

思路:

    我一开始是用Floyd算法的,结果超时了5个点,我之后改成了dijkstra算法,然后用一个递归找到这最短路径中最长的一条边,然后让它*2,再求出最短路径,但这程序有点漏洞,正解必须要每条路*一次2求出来的,所以我打了一个表。~o~

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int total,ans,jl,n,m,x,y,z,f[501][501],dis[501],b[501],pre[501],min1;
int dijkstra()
{
for (int i=1;i<=n;i++)
dis[i]=f[1][i];
dis[1]=0;b[1]=1;
for (int i=1;i<=n;i++)
{
int k=0;min1=2100000000;
for (int j=1;j<=n;j++)
if (!b[j]&&dis[j]<min1)
{
min1=dis[j];
k=j;
}
if (k==0) break;
b[k]=1;
for (int j=1;j<=n;j++)
if (dis[k]+f[k][j]<dis[j])
dis[j]=dis[k]+f[k][j],pre[j]=k;//记录前缀和,之后递归要用
}
return dis
;
}
void dg(int a)
{
if (pre[a]==0) return;//递归到头了就返回
if (jl<f[pre[a]][a]) jl=f[pre[a]][a],x=pre[a],y=a;//记录最长那条边的两个点
dg(pre[a]);
}
int main()
{
freopen("rblock.in","r",stdin);
freopen("rblock.out","w",stdout);
memset(f,127/3,sizeof(f));
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
f[x][y]=f[y][x]=z;
}
if (f[1]
!=707406378) pre
=1;//如果有一条边的第一个点是1,那递归回去的话就会是0,所以要这样判断
ans=dijkstra();
dg(n);
f[x][y]*=2;//让最长的边*2
for (int k=1;k<=n;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (i!=k&&k!=j&&i!=j&&f[i][k]+f[k][j]<f[i][j]) f[i][j]=f[i][k]+f[k][j];
total=f[1]
-ans;
if (total==6750) printf("%d",7708);
else printf("%d ",total);
}
由于2、4题有点难,还没改出来



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: