上周日的题解居然拖到现在才写……
上周六去蹭算法课顺便蹭了作业,搜索我一向比较弱……
A:hdu1010
Tempter of the Bone
Problem Description
The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.
The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.
Input
The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:
'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.
The input is terminated with three 0's. This test case is not to be processed.
Output
For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.
Sample Input
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0
Sample Output
走迷宫,问能否恰好k步从起点走到终点。
其实不难但是搞了很久,第二个剪枝还是看网上的题解才知道的。
典型的深搜,有两个减枝
1.当前的步数加上最少的到终点的步数大于了k,不可能走得到
2.当前的步数加上最少的到终点的步数减去k为奇数,也不可能走得到(简单地说就是(假设s在t的左边)只要向左走了一步就一定得向右走一步回到那一列)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<math.h>
#include<stdlib.h>
using namespace std;
const long k[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int flag;
long n,m,t;
long sx,sy,tx,ty;
bool a[10][10];
void init()
{
memset(a,0,sizeof(a));
for(long i=1;i<=n;i++)
for(long j=1;j<=m;j++)
{
char c;
cin>>c;
if (c=='S') {sx=i;sy=j;a[i][j]=true;}
if (c=='D') {tx=i;ty=j;a[i][j]=true;}
if (c=='.') {a[i][j]=true;}
}
}
void dfs(long x,long y,long d)
{
if (flag) return;
if((d==t)&&(x==tx)&&(y==ty)){ flag=true;return;}
if (d>=t) return;
long dis=abs(x-tx)+abs(y-ty);
if((dis>t)||(dis+t-d)%2!=0) return;
a[x][y]=false;
for (long i=0;i!=4;i++)
{
long tmpx=x+k[i][0];
long tmpy=y+k[i][1];
if ((a[tmpx][tmpy]))
{
a[tmpx][tmpy]=false;
//cout<<tmpx<<" "<<tmpy<<" "<<d+1<<endl;
dfs(tmpx,tmpy,d+1);
a[tmpx][tmpy]=true;
}
}
}
int main()
{
cin>>n>>m>>t;
while ((n!=0)&&(m!=0)&&(t!=0))
{
init();
if((abs(tx-sx)+abs(ty-sy))>t)
{cout<<"NO"<<endl;}
else{
flag=false;
dfs(sx,sy,0);
if (flag)
cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
cin>>n>>m>>t;
}
return 0;
}
B:hdu1204:
Asteroids!
Problem Description
You're in space.
You want to get home.
There are asteroids.
You don't want to hit them.
Input
Input to this problem will consist of a (non-empty) series of up to 100 data sets. Each data set will be formatted according to the following description, and there will be no blank lines separating data sets.
A single data set has 5 components:
Start line - A single line, "START N", where 1 <= N <= 10.
Slice list - A series of N slices. Each slice is an N x N matrix representing a horizontal slice through the asteroid field. Each position in the matrix will be one of two values:
'O' - (the letter "oh") Empty space
'X' - (upper-case) Asteroid present
Starting Position - A single line, "A B C", denoting the <A,B,C> coordinates of your craft's starting position. The coordinate values will be integers separated by individual spaces.
Target Position - A single line, "D E F", denoting the <D,E,F> coordinates of your target's position. The coordinate values will be integers separated by individual spaces.
End line - A single line, "END"
The origin of the coordinate system is <0,0,0>. Therefore, each component of each coordinate vector will be an integer between 0 and N-1, inclusive.
The first coordinate in a set indicates the column. Left column = 0.
The second coordinate in a set indicates the row. Top row = 0.
The third coordinate in a set indicates the slice. First slice = 0.
Both the Starting Position and the Target Position will be in empty space.
Output
For each data set, there will be exactly one output set, and there will be no blank lines separating output sets.
A single output set consists of a single line. If a route exists, the line will be in the format "X Y", where X is the same as N from the corresponding input data set and Y is the least number of moves necessary to get your ship from the starting position to the target position. If there is no route from the starting position to the target position, the line will be "NO ROUTE" instead.
A move can only be in one of the six basic directions: up, down, left, right, forward, back. Phrased more precisely, a move will either increment or decrement a single component of your current position vector by 1.
Sample Input
START 1
O
0 0 0
0 0 0
END
START 3
XXX
XXX
XXX
OOO
OOO
OOO
XXX
XXX
XXX
0 0 1
2 2 1
END
START 5
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
XXXXX
XXXXX
XXXXX
XXXXX
XXXXX
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
0 0 0
4 4 4
END
Sample Output
一个三维空间的广搜。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
struct point
{
long x,y,z;
};
const long k[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
long n;
point s,t;
bool a[12][12][12];
long d[12][12][12];
point du[1040]={0};
long l=1,r=1;
void init()
{
memset(a,0,sizeof(a));
memset(d,0,sizeof(d));
for(long k=0;k<n;k++)
for(long i=0;i<n;i++)
for(long j=0;j<n;j++)
{
char c;
cin>>c;
if (c=='O') {a[i][j][k]=true;}
if (c=='X') {a[i][j][k]=false;}
}
cin>>s.x>>s.y>>s.z;
cin>>t.x>>t.y>>t.z;
}
long bfs(point s)
{
du[r++]=s;
a[s.x][s.y][s.z]=false;
d[s.x][s.y][s.z]=0;
while (l<r)
{
point tmp=du[l++];
for (long i=0;i!=6;i++)
{
point tmp1;
tmp1.x=tmp.x+k[i][0];
tmp1.y=tmp.y+k[i][1];
tmp1.z=tmp.z+k[i][2];
if (a[tmp1.x][tmp1.y][tmp1.z])
{
du[r++]=tmp1;
a[tmp1.x][tmp1.y][tmp1.z]=false;
d[tmp1.x][tmp1.y][tmp1.z]=d[tmp.x][tmp.y][tmp.z]+1;
// cout<<tmp1.x<<" "<<tmp1.y<<" "<<tmp1.z<<" "<<d[tmp1.x][tmp1.y][tmp1.z]<<" "<<d[tmp.x][tmp.y][tmp.z]<<endl;
if ((tmp1.x==t.x)&&(tmp1.y==t.y)&&(tmp1.z==t.z))
{
return (d[tmp1.x][tmp1.y][tmp1.z]);
}
}
}
}
return false;
}
int main()
{
string s1;
while (cin>>s1>>n)
{
// cout<<s1<<endl;
init();
if ((s.x==t.x)&&(s.y==t.y)&&(s.z==t.z)) cout<<n<<" "<<0<<endl;
else {
long tmp=bfs(s);
if (tmp==0) cout<<"NO ROUTE"<<endl;
else cout<<n<<" "<<tmp<<endl;
}
cin>>s1;
}
return 0;
}
C:
Oil Deposits
Problem Description
The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid.
Input
The input file contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either `*', representing the absence of oil, or `@', representing an oil pocket.
Output
For each grid, output the number of distinct oil deposits. Two different pockets are part of the same oil deposit if they are adjacent horizontally, vertically, or diagonally. An oil deposit will not contain more than 100 pockets.
Sample Input
1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0
Sample Output
数有为‘@’的块的个数,搜索计数就可以了(程序比较奇葩…………)
注意一下不只是上下左右与当前相邻,共用顶点也是相邻的!!(这提醒我们要认真读题!!)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<math.h>
#include<stdlib.h>
using namespace std;
long n,m;
char a[200][200];
void init()
{
memset(a,0,sizeof(a));
for(long i=1;i<=n;i++)
for(long j=1;j<=m;j++)
{
cin>>a[i][j];
if (a[i][j]=='@')
a[i][j]=1;
else a[i][j]=0;
}
}
void change(long i,long j)
{
long k,l;
a[i][j]=0;
if(a[i-1][j]>0) change(i-1,j);
if(a[i+1][j]>0) change(i+1,j);
if(a[i][j-1]>0) change(i,j-1);
if(a[i][j+1]>0) change(i,j+1);
if(a[i-1][j-1]>0) change(i-1,j-1);
if(a[i+1][j+1]>0) change(i+1,j+1);
if(a[i-1][j+1]>0) change(i-1,j+1);
if(a[i+1][j-1]>0) change(i+1,j-1);
}
int main()
{
cin>>n>>m;
while ((n!=0)&&(m!=0))
{
init();
long cnt=0;
for(long i=1;i<=n;i++)
for(long j=1;j<=m;j++)
{
if (a[i][j]!=0)
{
change(i,j);
cnt++;
}
}
cout<<cnt<<endl;
cin>>n>>m;
}
return 0;
}
D:hdu 1238
Substrings
Problem Description
You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings.
Input
The first line of the input file contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains a single integer n (1 <= n <= 100), the number of given strings, followed by n lines, each representing one string of minimum length 1 and maximum length 100. There is no extra white space before and after a string.
Output
There should be one line per test case containing the length of the largest string found.
Sample Input
2
3
ABCD
BCDFF
BRCD
2
rose
orchid
Sample Output
大意:求若干个串的最长公共串的长度(可以正向也可以是反向的)
方法就是拿最短的串从长度为1的每个子串(或者这个子串的反向串)与其他的串做匹配,如果成功就增加长度,失败就将子串起点后移
#include <algorithm>
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
string a[110];
string s1;
long t,n;
void init()
{
cin>>n;
for(long i=0;i<n;i++)
{
cin>>a[i];
}
s1=a[0];
long tmp=0;
for(long i=1;i<n;i++)
{
if (a[i].size()<s1.size())
{
tmp=i;
s1=a[i];
}
}
s1=a[tmp];
a[tmp]=a[0];
a[0]=s1;
}
void find_max()
{
s1=a[0];
long maxn=0;
for(long i=0;i<=s1.size();i++)
{
for (long j=1;j+i<=s1.size();j++)
{
string st1="",st2="";
st1=s1.substr(i,j);
st2=st1;
reverse(st2.begin(),st2.end());
//cout<<st1<<" "<<st2<<endl;
bool t=true;
for (long k=1;k<n;k++)
{
if ((a[k].find(st1,0)==string::npos)&&(a[k].find(st2,0)==string::npos))
{
t=false;
break;
}
}
if (!t) { break;}
if (j>maxn) maxn=j;
}
}
cout<<maxn<<endl;
}
int main()
{
// freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
cin>>t;
for (long i=1;i<=t;i++)
{
init();
find_max();
}
return 0;
}