ACM第三周周报

枯木逢春不再茂 ,年少且惜镜边人

这周题有点难,调了几个差不多会的做了做;
1
定义一个二维数组:

int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
Input

   一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
  Output
  
   左上角到右下角的最短路径,格式如样例所示。
  Sample Input0 1 0 0 0

0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0Sample Output(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

#include<stdio.h>
struct note
{
	int x;
	int y;
	int pre; 
};
struct note que[2501];
int a[51][51]={0},book[51][51]={0};
void f(int i)
{
	if(que[i].pre!=-1)
	{
		f(que[i].pre);
		printf("(%d, %d)\n",que[i].x,que[i].y);
	}
}
int main()
{
	int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
	int head,tail;
	int i,j,k,n,m,startx,starty,p,q,tx,ty;
	for(i=0;i<5;i++)
      for(j=0;j<5;j++)
	  scanf("%d",&a[i][j]);
	 head=0;tail=1;
	 startx=0;starty=0;
	 que[head].x=startx;
	 que[head].y=starty;
	 que[head].pre=-1;
	 book[startx][starty]=1;
	 printf("(0, 0)\n");
	  while(head<tail)
	 {
	 	for(k=0;k<=3;k++)
	 	{
	 		tx=que[head].x+next[k][0];
	 		ty=que[head].y+next[k][1];
	 		if(tx<0||tx>4||ty<0||ty>4)
	 		continue;
	 		if(a[tx][ty]==0&&book[tx][ty]==0)
	 		{
	 			book[tx][ty]=1;
	 			que[tail].x=tx;
	 			que[tail].y=ty;
	 			que[tail].pre=head;
	 			tail++;
			 }
			 if(tx==4&&ty==4)
			 f(head);
		 }
		 head++;
	}
	printf("(4, 4)"); 
} 

**这是一个bfs问题,
void f(int i)
{
if(que[i].pre!=-1)
{
f(que[i].pre);
printf("(%d, %d)\n",que[i].x,que[i].y);
}
},这个方法叫什么追尾法什么的,pre是que【i】 的前面的那个。所以可以一直追踪!,但是最后一步无法指明,还有第一步所以得手写出来。
**
2.
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input

   输入含有多组测试数据。 

每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n

当为-1 -1时表示输入结束。

随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。

  Output
  
   对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
  Sample Input2 1

#.
.#
4 4
…#
…#.
.#…
#…
-1 -1
Sample Output2
1

#include<stdio.h>

#include<string.h>

char map[9][9];

int vis[50],n,k,ans;

void dfs(int m,int k)//m代表层数,k代表棋子数。

{
	int i,j; 
    if(k==0)

    {

        ans++;

        return ;

    }

    for( i=m;i<n;i++)//枚举每一行,每一列摆放旗子的可能。

        for( j=0;j<n;j++)

    {

        if(map[i][j]=='.'||vis[j]==1) 
        continue;

        vis[j]=1;

        dfs(i+1,k-1);//行数加一,棋子数减一。

        vis[j]=0;

    }

}

int main()

{
	int i,j;

    while(~scanf("%d %d",&n,&k))

    {

        if(n==-1&&k==-1)

            break;

        for(i=0;i<n;i++)

            scanf("%s",&map[i]);

        memset(vis,0,sizeof(vis));

        ans=0;

        dfs(0,k);

        printf("%d\n",ans);

    }

    return 0;

}

就在代码里标注吧,简单的跑图题。

You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot move diagonally and the maze is surrounded by solid rock on all sides.

Is an escape possible? If yes, how long will it take?

  Input
  
   The input consists of a number of dungeons. Each dungeon description starts with a line containing three integers L, R and C (all limited to 30 in size). 

L is the number of levels making up the dungeon.

R and C are the number of rows and columns making up the plan of each level.

Then there will follow L blocks of R lines each containing C characters. Each character describes one cell of the dungeon. A cell full of rock is indicated by a ‘#’ and empty cells are represented by a ‘.’. Your starting position is indicated by ‘S’ and the exit by the letter ‘E’. There’s a single blank line after each level. Input is terminated by three zeroes for L, R and C.
Output

   Each maze generates one line of output. If it is possible to reach the exit, print a line of the form 
   

   
    Escaped in x minute(s). 

where x is replaced by the shortest time it takes to escape.

If it is not possible to escape, print the line

    Trapped! 
   
  Sample Input3 4 5

S…
.###.
.##…
###.#

##.##
##…

#.###
####E

1 3 3
S##
#E#

0 0 0
Sample OutputEscaped in 11 minute(s).
Trapped!

#include<stdio.h>
#include<string.h>
int next[6][3] = {{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};//三个数字分别表示X,Y,Z;
struct note
{
	int x,y,z,s;
};
int i,j,z,startx,starty,t,startz,tx,ty,tz,p,q,r,flag,m,n,k,ans;
struct note que[100000];
int  book[35][35][35]={0};
char map[35][35][35];
int head,tail;
int check(int x,int y,int z)
{
    if(x<0 || y<0 || z<0 || x>=k || y>=n || z>=m)
	        return 1;
    else if(map[x][y][z] == '#')        
	   return 1;   
	else if(book[x][y][z])        
	   return 1;    
	return 0;
}

int bfs()
{
	head=1;tail=1;
	que[tail].x=startx;
	que[tail].y=starty;
	que[tail].z=startz;
	que[tail].s=0;
	tail++;
	book[startx][starty][startz]=1;
	flag=0;
	while(head<tail)
	{
		for(t=0;t<6;t++)
		{
			tx=que[head].x+next[t][0];
			ty=que[head].y+next[t][1];
			tz=que[head].z+next[t][2];
			if(check(tx,ty,tz))
			continue;
		    else
			{
				book[tx][ty][tz]=1;
				que[tail].x=tx;
				que[tail].y=ty;
				que[tail].z=tz;
				que[tail].s=que[head].s+1;
				tail++;
			}
			if(tx==p&&ty==q&&tz==r)
			{
				flag=1;
				break;
			}
		}
			if(flag==1)
			{
				break;
			}
			head++;
	}
		return que[tail-1].s;
}
int main()
{
	while(scanf("%d %d %d",&k,&n,&m),k+n+m)
	{
		for(i=0;i<k;i++)
		{
			for(j=0;j<n;j++)
			{
				scanf("%s",map[i][j]);
				for(z=0;z<m;z++)
				{
					if(map[i][j][z]=='S')
					{
						startx=i;
						starty=j;
						startz=z;
					}
					else if(map[i][j][z]=='E')
					{
						p=i;q=j;r=z;
				    }
				}
			}
	    }
		memset(book,0,sizeof(book));
		ans=bfs();
	    if(ans)
	        printf("Escaped in %d minute(s).\n",ans);
	    else
	        printf("Trapped!\n");
	    ans=0;
    }
    return 0;
	
}

是一个三维数组的bfs,记录步数就OK,三维数组写起来要细心,那就在代码里面标注吧。简单的标注了,会二维bfs都能看懂
5.
Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in which they manipulate an M × N grid (1 ≤ M ≤ 15; 1 ≤ N ≤ 15) of square tiles, each of which is colored black on one side and white on the other side.
As one would guess, when a single white tile is flipped, it changes to black; when a single black tile is flipped, it changes to white. The cows are rewarded when they flip the tiles so that each tile has the white side face up. However, the cows have rather large hooves and when they try to flip a certain tile, they also flip all the adjacent tiles (tiles that share a full edge with the flipped tile). Since the flips are tiring, the cows want to minimize the number of flips they have to make.
Help the cows determine the minimum number of flips required, and the locations to flip to achieve that minimum. If there are multiple ways to achieve the task with the minimum amount of flips, return the one with the least lexicographical ordering in the output when considered as a string. If the task is impossible, print one line with the word “IMPOSSIBLE”.
Input

   Line 1: Two space-separated integers: 
   M and 
   N 

Lines 2…
M+1: Line
i+1 describes the colors (left to right) of row i of the grid with
N space-separated integers which are 1 for black and 0 for white
Output

   Lines 1..
   M: Each line contains 
   N space-separated integers, each specifying how many times to flip that particular location.
  Sample Input4 4

1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1Sample Output0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0

这道题运用了二进制,就是例如4位的二进制可以表示16中 情况,而且运用了掩码运算。

#include<stdio.h>
#include<string.h>
#define N 16

int g[N][N], t[N][N], f[N][N];
int cnt, n, m;
int x[4] = {0, 0, -1, 1};
int y[4] = { -1, 1, 0, 0};
void flip(int i, int j)

{
	int k;

    ++cnt, f[i][j] = 1;//步数加一,并且标记。
    t[i][j] = !t[i][j];//翻转自己

    for(k = 0; k < 4; ++k)
        if(i + x[k] > -1 && j + y[k] > -1)

            t[i + x[k]][j + y[k]] ^= 1;//向四个方向寻找,这里使用了异或,亦或就是相同为0,不同为1,因为题目要求翻一个,动4个。

}

 

int ok(int k)
{
	 int i,j;
    cnt = 0;

    memcpy(t, g, sizeof(t));//复制原表

    for( j = 0; j < m; ++j)

        if(k & (1 << (m - 1 - j)))//通过掩码运算求出翻转的点

            flip(0, j);

 

 

    for( i = 1; i < n; ++i)

        for( j = 0; j < m; ++j)

            if(t[i - 1][j]) 
			flip(i, j);//看上一行是否为1,若为1则翻转

 

    for( j = 0; j < m; ++j)

        if(t[n - 1][j]) //看最后一行是否是全是0
		return 0;

    return 1;

}

 

int main()

{

    int ans, p;
    int i,j;

    while(~scanf("%d %d", &n, &m))

    {

        for( i = 0; i < n; ++i)

            for( j = 0; j < m; ++j)

                scanf("%d", &g[i][j]);

        ans = n * m + 1, p = -1;

        for(i = 0; i < (1 << m); ++i)//列举每一种情况

            if(ok(i) && cnt < ans) //判断是这种情况的步数,和情况。
                ans = cnt, p = i;

 

        memset(f, 0, sizeof(f));

        if(p >= 0)

        {

            ok(p);

            for(i = 0; i < n; ++i)

                for( j = 0; j < m; ++j)

                    printf("%d%c", f[i][j], j < m - 1 ? ' ' : '\n');

        }

        else puts("IMPOSSIBLE");

    }

    return 0;

}

这么厉害的代码当然是参考别人写的,大家看看就好
5.
My birthday is coming up and traditionally I’m serving pie. Not just one pie, no, I have a number N of them, of various tastes and of various sizes. F of my friends are coming to my party and each of them gets a piece of pie. This should be one piece of one pie, not several small pieces since that looks messy. This piece can be one whole pie though.

My friends are very annoying and if one of them gets a bigger piece than the others, they start complaining. Therefore all of them should get equally sized (but not necessarily equally shaped) pieces, even if this leads to some pie getting spoiled (which is better than spoiling the party). Of course, I want a piece of pie for myself too, and that piece should also be of the same size.

What is the largest possible piece size all of us can get? All the pies are cylindrical in shape and they all have the same height 1, but the radii of the pies can be different.
Input

   One line with a positive integer: the number of test cases. Then for each test case:
   
    One line with two integers N and F with 1 ≤ N, F ≤ 10 000: the number of pies and the number of friends.
    One line with N integers ri with 1 ≤ ri ≤ 10 000: the radii of the pies.
   
  Output
  
   For each test case, output one line with the largest possible volume V such that me and my friends can all get a pie piece of size V. The answer should be given as a floating point number with an absolute error of at most 10
   −3.
  Sample Input3

3 3
4 3 3
1 24
5
10 5
1 4 2 3 4 5 6 5 4 2Sample Output25.1327
3.1416
50.2655

#include<stdio.h>
#define pi 3.1415926535868
int main()
{
	int n,i,f,t,r,sum2;
	double a[10003];
	double min,max,mid,s,sum=0;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&n,&f);
		for(i=0;i<n;i++)
		{
			scanf("%d",&r);
			s=pi*r*r;//求体积
			a[i]=s;
			sum=a[i]+sum;//体积最大
		}
		min=0;max=(sum/(f+1))*1.0;//最大没人能分到蛋糕体积 
		while(min+1e-4<max)//其实就是判断MIN 和 MAX不想同
		{
				mid=(max+min)/2;//开始二分
				sum2=0;
				for(i=0;i<n;i++)
				{
					sum2=(int)(a[i]/mid)+sum2;//可以分到的人数
				}
				if(sum2>=(f+1))
				min=mid;//人数多的话就分更多的
				else//否则每人分少点
				max=mid;
		}
		printf("%.4lf\n",mid);
	}
	return 0;
 } 

主要思想就是二分的思想,具体看代码
6.
Now,given the equation 8x^4 + 7x^3 + 2x^2 + 3x + 6 == Y,can you find its solution between 0 and 100;

Now please try your lucky.
InputThe first line of the input contains an integer T(1<=T<=100) which means the number of test cases. Then T lines follow, each line has a real number Y (fabs(Y) <= 1e10);OutputFor each test case, you should just output one real number(accurate up to 4 decimal places),which is the solution of the equation,or “No solution!”,if there is no solution for the equation between 0 and 100.Sample Input2
100
-4Sample Output1.6152
No solution!

#include<stdio.h> 
#include<math.h>
  double f(double x)
  {
     return (8*x*x*x*x+7*x*x*x+2*x*x+3*x+6);
   } 
  int main()
  {
      
    int t;
      double l,r;
     while(~scanf("%d",&t))
     {
         while(t--)
         {
             double y;
             scanf("%lf",&y);
             if(f(0)>y||f(100)<y)//递增,判断是否是0~100之间的解。
             {
                 printf("No solution!\n");
                 continue;
             }
           
             l=0.0;r=100.0;
             double mid=50.0;
             while(fabs(f(mid)-y)>1e-5)//判断不相等
             {
                 if(f(mid)>y)
                 {
                     r=mid;
                     mid=(l+r)/2.0;
                     
                 }
                 else
                 {
                     l=mid;
                     mid=(l+r)/2.0;
                 }
                 
             }
             printf("%.4lf\n",mid);
         }
     }
     return 0;
 }

也是一个二分的问题,找0~100里的解
6
.
大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。
Input三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。Output如果能平分的话请输出最少要倒的次数,否则输出"NO"。Sample Input7 4 3
4 1 3
0 0 0Sample OutputNO
3
这道题不太会,理解了大佬的代码,说是广度优先搜索,进行6种情况的搜索

#include<stdio.h>
#include<string.h>
int b[3],book[101][101][101],half;

struct node

{

    int cur[3],s;        //cur表示各个被子的可乐含量


}p,temp;         
struct node que[100000];
void bfs()
{
	int head=1,tail=1;
    que[tail].cur[0]=b[0];         
    que[tail].cur[1]=que[tail].cur[2]=que[tail].s=0;//每次都置0  
    tail++;                  
    while(head<tail)//bfs
    {
    	p=que[head];

        for(int i=0;i<3;i++)     
        {

            if(p.cur[i]>0)      

            {

                for(int j=0;j<3;j++)  

                {

                    temp=p;
					        
                    if(i==j)  continue ;   
                    if(temp.cur[i]>b[j]-temp.cur[j])   
                    {
                        temp.cur[i]-=b[j]-temp.cur[j];    
                        temp.cur[j]=b[j];
                    }
                    else    
                    {
                        temp.cur[j]+=temp.cur[i];
                        temp.cur[i]=0;
                    }
                    if(!book[temp.cur[0]][temp.cur[1]][temp.cur[2]])  
                    {
                        book[temp.cur[0]][temp.cur[1]][temp.cur[2]]=1; 
                        temp.s++;
                        if((temp.cur[0]==half&&temp.cur[1]==half)|| (temp.cur[0]==half&&temp.cur[2]==half)||(temp.cur[1]==half&&temp.cur[2]==half))
                            {
                                printf("%d\n",temp.s);
                                return ;             

                            }
                            que[tail]=temp;
                            tail++;
                            head++;
                    }

                }

            }

        }
    }

       printf("NO\n"); 
}

int main()

{

    while(scanf("%d %d %d",&b[0],&b[1],&b[2]),b[0]+b[1]+b[2])  

    {

        memset(book,0,sizeof(book));  

        book[b[0]][b[1]][b[2]]=1;   

        if(b[0]%2)   printf("NO\n"); 

        else 
		{
		half=b[0]/2;
		bfs();
		}

    }

    return 0;

}

这道题大家理解就好,3个杯子倒的方式有6种1 2 ,1 3 , 2 1 ,2 3,3 1,3 2;
今天就到此为止了。

发布了8 篇原创文章 · 获赞 1 · 访问量 661

猜你喜欢

转载自blog.csdn.net/WOF_Spark/article/details/104338201