湖南师范大学第三届大学生计算机程序设计竞赛(网络同步赛)部分解题
F题最后都没出非常不爽
A.原码转补码
水题:注意-0

#include<string.h>
#include<stdlib.h>
#include<stdio.h>
char as[100];
int main()
{
int i,j,k,t;
scanf("%d",&t);
while(t--)
{
scanf("%s",as);
if( as[0]=='0')puts(as);
else{
for( i=0; as[i]; ++i ) as[i]-='0';
k=0;
for( i=1; i<8; i++ ) k=k*2+as[i];
if( k!=0 ){//特判-0
for( i=1; i<8; ++i ) as[i]^=1;
for( i=7,k=1; i>=0; i-- ){
as[i]+=k;
k=0;
if(as[i]>1 ){ as[i]=0; k=1;}
}
}
for( i=0; i<8; i++ )putchar(as[i]+'0');
puts("");
}
}return 0;
}
B.大魔术师
记得是大一时候的c语言课程设计的题目之一,当时就可以弄出来了,今天还是卡了一下。
思路:设k为当前剩下的空位数,当前记数的空位位置为j,则可以得到下一个值i要插入的位置为tp=i%k,
然后从j开始计数空位数,计数到tp时,就好了。

#include<stdio.h>
#include<string.h>
int as[1005],bs[1005],n;
int fun(int k,int x)
{
int i=x,j=1;
while(j<k){
++i;
if( i>n ) i=1;
if(!as[i]) j++;
}
return i;
}
int main()
{
int i,j,k,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for( i=1; i<=n; i++ )scanf("%d",bs+i);
memset(as,0,sizeof(as));
j=1; k=n;
for( i=1; i<n; i++,k-- ){
int tp=i%k; //tp为从j开始的空位后,第tp个就是i要插入的值了。
if( !tp ) tp=k;
j=fun(tp,j);//从j开始,找第tp个空位
as[j]=i;
while(1){//寻找下一个空位
if(!as[j])break;
j++;
if(j>n)j=1;
}
}
as[j]=i;
for(i=1; i<n; i++ )printf("%d ",bs[as[i]]);
printf("%d\n",bs[as[i]]);
}return 0;
}
C.A Math Problem
思路:根据三角形面积 s=a*b*sin(60)/2可先算出三个角的三角形面积,用大的减去它们就好了.

D.Imagination
思路:直接dfs模拟就好了

#include<stdio.h>
#include<string.h>
int as[105][105];
int l,r,u,d,n;
void dfs(int x,int y,int cnt,int flag)
{
as[x][y]=cnt;
if( cnt==n*n)return ;
if( flag==1){//向左方向
if( y<l ) dfs(x,y+1,cnt+1,flag);
else if( y==l ){ //转到向下
++u;
dfs(x+1,y,cnt+1,2);
}
}
if( flag==2){ //向下方向
if( x<n )dfs(x+1,y,cnt+1,flag);
else if( x==n){ --l; dfs(x,y-1,cnt+1,3); }//转到向上
}
if( flag==3){ //向上方向
if( x>u ) dfs(x-1,y,cnt+1,flag);
else if( x==u) { --l; dfs(x,y-1,cnt+1,4); }//转到向右
}
if( flag==4 ){ //向右方向
if( y>1 ) dfs(x,y-1,cnt+1,flag);
else if( y==1 ){ ++u; dfs(x+1,y,cnt+1,1);} //转到向左
}
}
int main()
{
int i,j,k,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
l=n; u=1;
dfs(1,1,1,1);
for( i=1; i<=n; i++ )
{
for( j=1; j<n; j++ )printf("%d ",as[i][j]);
printf("%d\n",as[i][j]);
}
}return 0;
}
E.The Minesweeper Game
思路:bfs直接暴力维护一个队列,如果当前点的八个方向(开始想是四个方向,sb的搞了一个多小时,查查)都能走就入队。(dfs应该也可以做的,估计王相是dfs过的)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char map[50][50];
int as[50][50];
int bs[50][50];
int cs[50][50];
int que[100000][3];
int dx[]={0,1,-1,0,-1,1,-1,1};
int dy[]={1,0,0,-1,-1,1,1,-1};
int si,sj;
bool isok(int x,int y)
{
// puts("isok");
return !(x<1||y<1||x>16||y>30||map[x][y]=='*'||bs[x][y]==-1);
}
int ok(char c)
{
return c=='*'?1:0;
}
int count(int x,int y)//计算八个方向的雷总数
{
// puts("count");
int cnt=0;
cnt+=ok(map[x+1][y]);
cnt+=ok(map[x][y+1]);
cnt+=ok(map[x-1][y]);
cnt+=ok(map[x][y-1]);
cnt+=ok(map[x+1][y-1]);
cnt+=ok(map[x+1][y+1]);
cnt+=ok(map[x-1][y+1]);
cnt+=ok(map[x-1][y-1]);
return cnt;
}
void bfs()
{
int ts=0,te=1,x,y,k,i,j;
memset(que,0,sizeof(que));
que[ts][0]=si;
que[ts][1]=sj;
k=count(si,sj);
bs[si][sj]=-1;
cs[si][sj]=1;
if(k){
as[si][sj]=k;
return ;
}
while(ts<te)
{
for( i=0; i<8; i++ ){
x=que[ts][0]+dx[i];
y=que[ts][1]+dy[i];
if(isok(x,y)||(cs[x][y]&&bs[x][y]!=-1)){
k=count(x,y);
bs[x][y]=-1;
if(k){
as[x][y]=k;
continue;
}
que[te][0]=x;
que[te][1]=y;
++te;
}
}ts++;
}
}
int main()
{
int i,j,k,t;
scanf("%d",&t);
while(t--)
{
memset(map,0,sizeof(map));
memset(bs,0,sizeof(bs));
memset(cs,0,sizeof(cs));
memset(as,0,sizeof(as));
scanf("%d%d",&si,&sj);
for( i=1; i<=16; i++ )scanf("%s",map[i]+1);
bfs();
for( i=1; i<=16; i++ ){
for( j=1; j<=30; j++ ){
if( bs[i][j]==-1 ) printf("%d",as[i][j]);
else putchar('#');
}
puts("");
}
if(t)puts("");
}return 0;
}
F.Adventure of Super Mario
题意:一个世界有a个村和b个城堡,1~a为村,a+1~a+b为城堡,一个人要从第a+b个城堡回家1,他有一双魔法鞋,可以不耗时间的穿越某些路径,但是每次经过的总长度不能超过L,而且最多能用k次,且还有以个规定:
1.如果穿越的时候遇到城堡,必须停;
2.如果小当前剩下的能穿越长度不够穿越下一路径,则不能再用剩下的;
3.穿越的起点和终点都必须是村和城堡(不允许半路停)。
4.求从a+b到家1的最短路径。
思路:典型的dfs+剪枝(最短路径spfa)
大概看到题的时候就无限YY以前做过类似的题目,结果题被我从简单的YY到难的,再从难的YY到简单的,代码也写了几个版本,ac的时候气死人了,它的题目描述真的太差了:模凌两可(可能是我自己的原因)。
先spfa出没穿越时的最短路径,然后用来给dfs剪枝,不断更新。dfs枚举每条边穿越不穿越两种情况。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int inf=0xfffffff;
int mmap[105][105];
int vis[105];
int que[20000],dis[105];
int n,l,ans,a,b;
int spfa(int s,int t)
{
int i,k,ts=0,te=1;
for( i=1; i<=n; i++ ){ vis[i]=0; dis[i]=inf; }
que[ts]=s;
dis[s]=0;
while(ts<te){
k=que[ts];
vis[k]=0;
for( i=1; i<=n; i++ ){
if(dis[i]-mmap[k][i]>dis[k]){
dis[i]=mmap[k][i]+dis[k];
if(!vis[i]){
que[te++]=i;
vis[i]=1;
}
}
}ts++;
}return dis[t];
}
void dfs(int x,int cnt,int k,int cl)
{
int i,j;
if( cnt>ans )return ;
if(x==1){
if( ans>cnt) ans=cnt;
return ;
}
for( i=n; i>0; i-- ){
if((i!=x)&&(mmap[x][i]!=inf)&&(!vis[i])){
vis[i]=1;
dfs(i,cnt+mmap[x][i],k,0);
if(i>a){//为城堡的时候
if(cl>=mmap[x][i])dfs(i,cnt,k,0);
else if(k&&l>=mmap[x][i])dfs(i,cnt,k-1,0);
}
else if( cl>=mmap[x][i] ) dfs(i,cnt,k,cl-mmap[x][i]);
else if(k) if(l>=mmap[x][i]) dfs(i,cnt,k-1,l-mmap[x][i]);
vis[i]=0;
}
}
}
int main()
{
int i,j,k,m,t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d %d %d",&a,&b,&m,&l,&k);
n=a+b;
b+=a;
for( i=1; i<=n; i++ )
for( j=1; j<=n; j++ ) if(i==j)mmap[i][j]=0; else mmap[i][j]=inf;
for( i=0; i<m; i++ ){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
mmap[x][y]=mmap[y][x]=z;
}
ans=spfa(n,1);//没有它就超时了
memset(vis,0,sizeof(vis));
vis[n]=1;
if(k)
dfs(n,0,k,0);
printf("%d\n",ans);
}return 0;
}