POJ1111 给定起点,求连通块的周长。
从起点开始搜索,将所有符合要求的X块标记。然后查找已经标记的块,判断是否是X连通块的边界块,计算周长。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,x,y;
char mp[25][25];
bool mark[25][25];
int dir[8][2]={{-1,0},{1,0},{0,-1},{0,1},{-1,1},{1,-1},{1,1},{-1,-1}};
void dfs(int x,int y)
{
int i,j;
mark[x][y]=1;
for(i=0;i<8;i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(mp[xx][yy]=='X'&&!mark[xx][yy]&&xx>=0&&xx<n&&yy>=0&&yy<m)
{
dfs(xx,yy);
}
}
}
int main()
{
while(~scanf("%d%d%d%d",&n,&m,&x,&y))
{
if(m+n+x+y==0) break;
int i,j,k;
int num=0,sum=0;
memset(mark,0,sizeof(mark));
for(i=0;i<n;i++)
scanf("%s",mp[i]);
dfs(x-1,y-1);
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(mark[i][j])
{
num=0;
for(k=0;k<4;k++)
{
int xx=i+dir[k][0];
int yy=j+dir[k][1];
if(xx<0||xx>=n||yy<0||yy>=m||!mark[xx][yy])
num++;
}
sum+=num;
}
}
}
printf("%d\n",sum);
}
return 0;
}
POJ2738 两种方法取数最大比分相差多少。
第一个人取数的方法是从长远考虑,第二个人取数只取两边较大的那个数。记忆化搜索+dp。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
int a[1010];
int dp[1010][1010];
int dfs(int left,int right)
{
int ans1,ans2;
if(dp[left][right]!=-1) return dp[left][right];
if(left+1==right) return dp[left][right]=fabs(a[right]-a[left]);
if(a[left+1]>=a[right])
ans1=dfs(left+2,right)+a[left]-a[left+1];
else
ans1=dfs(left+1,right-1)+a[left]-a[right];
if(a[left]>=a[right-1])
ans2=dfs(left+1,right-1)+a[right]-a[left];
else
ans2=dfs(left,right-2)+a[right]-a[right-1];
return dp[left][right]=max(ans1,ans2);
}
int main()
{
int cnt=0;
while(scanf("%d",&n))
{
int i,j;
if(n==0) break;
for(i=0;i<n;i++)
scanf("%d",&a[i]);
memset(dp,-1,sizeof(dp));
printf("In game %d, the greedy strategy might lose by as many as %d points.\n",++cnt,dfs(0,n-1));
}
return 0;
}
POJ 2245 从指定的一系列数中挑选出六个数从小到大排列,输出所有可能的排列情况,按字典序排列。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int a[21],b[21];
void dfs(int len,int index)
{
int i,j;
if(len==6)
{
for(i=0;i<6;i++)
{
printf("%d",b[i]);
if(i!=5)
printf(" ");
else
printf("\n");
}
return;
}
if(index>=n||len+n-index<6) return;
b[len]=a[index];
dfs(len+1,index+1);
dfs(len,index+1);
}
int main()
{
int f=1;
while(~scanf("%d",&n))
{
int i,j;
if(!f) printf("\n");
if(n==0) break;
for(i=0;i<n;i++)
scanf("%d",&a[i]);
dfs(0,0);
f=0;
}
return 0;
}
POJ 2657
n个格子绕成一个环,从1开始走,z是目标格子,有m个格子是障碍格子,不能走。
dfs,走到重复的或者有障碍的,返回。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,z,m;
bool vis[1010];
bool flag,tag;
void dfs(int index,int k)
{
if(index==z||tag)
{
tag=1;
return;
}
if(flag)
return;
if(!vis[index])
{
vis[index]=1;
if(index+k>n)
{
dfs((index+k)%n,k);
}
else
dfs(index+k,k);
vis[index]=0;
}
else
flag=0;
}
int main()
{
int i,j,x;
scanf("%d%d%d",&n,&z,&m);
memset(vis,0,sizeof(vis));
for(i=1;i<=m;i++)
{
scanf("%d",&x);
vis[x]=1;
}
tag=0;
for(i=1;i<=n;i++)
{
flag=0;
dfs(1,i);
if(tag)
{
printf("%d\n",i);
break;
}
}
return 0;
}