- 题目一 FatMouse and Cheese
题目大意就是说有一个老鼠在N*N的网格当中每一步最多只能走K格 并且由于猫的存在每一次老鼠的移动都必须比路径上一个网格收集的奶酪多 问这条路径上老鼠收集的奶酪最大值
Sample Input
3 1
1 2 5
10 11 6
12 12 7
-1 -1
Sample Output
37
PS: 终点的位置不是固定的 满足上下左右都不存在比当前更大的网格的条件 即四周都比当前网格值小
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int n,k,nx,ny;
int vis[maxn][maxn],dp[maxn][maxn];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int dfs(int x,int y)
{
int i,j,nx,ny,ans=0;
if(dp[x][y])
return dp[x][y];//联系到第二个return 即已经进行赋值表示找到了最大路径
for(i=0;i<4;i++)
{
for(j=1;j<=k;j++)
{
nx=x+j*dx[i];//每次移动1~k个网格
ny=y+j*dy[i];
if(nx>0&&nx<=n&&ny>0&&ny<=n&&vis[nx][ny]>vis[x][y])
{
ans=max(ans,dfs(nx,ny));//一直往(nx,ny)的方向递归找最大路径
}
}
}
return dp[x][y]=ans+vis[x][y];//已经走到了终点加上终点的值
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n==-1&&k==-1)
break;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&vis[i][j]);
printf("%d\n",dfs(1,1));
}
return 0;
}
- 题目二 字符的全排列问题 有n个字符 请你输出该n个字符的全排列
Sample Input
1
abc
Sample Output
a b c
a c b
b a c
b c a
c a b
c b a
#include<stdio.h>
#include<string.h>
int n;
char a[15];
char re[15];
int vis[15];
void dfs(int step)
{
int i;
if(step==n+1)//判断边界
{
for(i=1;i<=n;i++)
printf("%c",re[i]);
printf("\n");
return ;
}
for(i=1;i<=n;i++)//遍历每一种情况
{
if(vis[i]==0)//check满足
{
re[step]=a[i];
vis[i]=1;//标记
dfs(step+1);//继续搜索
vis[i]=0;//恢复初始状态
}
}
return ;
}
int main(void)
{
int T;
scanf("%d",&T);
getchar();
while(T--)
{
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));//对存数据的数组分别初始化
scanf("%s",a+1);
n=strlen(a+1);
dfs(1);//从第一个箱子开始
}
return 0;
}
3.题目三 走迷宫
Sample Input
10 12
W…WW.
.WWW…WWW
…WW…WW.
…WW.
…W…
…W…W…
.W.W…WW.
W.W.W…W.
.W.W…W.
…W…W.
Sample Output
3
题目大意:w代表池塘 -代表水洼 八连通时表示该池塘积水 问有多少积水的池塘
用dfs搜索W的周围 若周围有w 则置为- 直到搜索完所有的点 图中剩下的就是积水池塘的个数
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e2+10;
int num=0,nx,ny,n,m;
char mp[maxn][maxn];
int dx[]={0,1,0,-1,0};
int dy[]={0,0,1,0,-1};
void dfs(int x,int y)
{
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
nx=x+dx[i];
ny=y+dy[i];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&mp[nx][ny]=='W')
{
mp[x][y]='.';
dfs(nx,ny);
}
}
}
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%c",&mp[i][j]);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(mp[i][j]=='W')
{
dfs(i,j);
num++;
}
}
}
printf("%d\n",num);
}
return 0;
}
4.题目四 How many ways
这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m)。游戏的规则描述如下:
1.机器人一开始在棋盘的起始点并有起始点所标有的能量。
2.机器人只能向右或者向下走,并且每走一步消耗一单位能量。
3.机器人不能在原地停留。
4.当机器人选择了一条可行路径后,当他走到这条路径的终点时,他将只有终点所标记的能量

机器人一开始在(1,1)点,并拥有4单位能量,蓝色方块表示他所能到达的点,如果他在这次路径选择中选择的终点是(2,4) 点,当他到达(2,4)点时将拥有1单位的能量,并开始下一次路径选择,直到到达(6,6)点。
我们的问题是机器人有多少种方式从起点走到终点。这可能是一个很大的数,输出的结果对10000取模。
Sample Input
1
6 6
4 5 6 6 4 3
2 2 3 1 7 2
1 1 4 6 2 7
5 8 4 3 9 5
7 6 6 2 1 5
3 1 1 3 7 2
Sample Output
3948
刚开始我的代码走的路径是上下左右然后选择比当前储存能量小的点搜下去直到终点 不过题目中表明了机器人只能往右或往下走 因此我们只要从左上角一只搜到右下角 然后右下角中的点储存的值就是我们最终的路径总数了
#include<stdio.h>
#define p 10000
int mp[120][120],vis[120][120];
int n,m,nx,ny;
long long dfs(int x,int y)
{
if(x==n&&y==m)//从起点走到了终点 只搜索了一次 总共也就只有一条路径
return 1;
if(vis[x][y]!=0)//所有点都尝试了以后输出最终的路径总数
return vis[x][y];
vis[x][y]=0;
for(int i=0;i<=mp[x][y];i++)//mp[x][y]是机器人当前的能量 而它要往下或往右走的格子是在当前能量够用的情况
{ //每走一步机器人将消耗一个能量
for(int j=0;j<=mp[x][y]-i;j++)
{
nx=x+i;
ny=y+j;
if((i!=0||j!=0)&&nx>=1&&nx<=n&&ny>=1&&ny<=m)//i,j不为零的意思是走的路不可能再加上起点
{
vis[x][y]+=dfs(nx,ny);
vis[x][y]%=p;
}
}
}
return vis[x][y];
}
int main()
{
int T,i,j;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&mp[i][j]);
vis[i][j]=0;//初始化 vis用来存放路径总数
}
}
printf("%lld\n",dfs(1,1));
}
return 0;
}
- Dividing
Sample Input
1 0 1 2 0 0
1 0 0 0 1 1
0 0 0 0 0 0
Sample Output
Collection #1:
Can't be divided.
Collection #2:
Can be divided.
没想到这道题居然还能使用广搜的方法来做 之前用的是dp(转换成多重背包)
广搜代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 2400
#define INF 0x3f3f3f3f//正无穷大
#define PI acos (-1.0)
#define EPS 1e-8
#define met(a, b) memset (a, b, sizeof (a))
typedef long long LL;
int a[N], half, flag;
void DFS (int v, int Index)
{
if (v == half)
{
flag = 1;
return;
}
for (int i=Index; i>=1; i--)
{
if (a[i])
{
if (v + i <= half)
{
a[i]--;
DFS (v+i, i);
if (flag) break;
}
}
}
return;
}
int main ()
{
int nCase = 1;
while (scanf ("%d %d %d %d %d %d", &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]))
{
int sum = a[1]+a[2]*2+a[3]*3+a[4]*4+a[5]*5+a[6]*6;
if (!sum) break;
printf ("Collection #%d:\n", nCase++);
if (sum % 2)
{
puts ("Can't be divided.\n");
continue;
}
flag = 0;
half = sum / 2;
DFS (0, 6);
if (flag) puts ("Can be divided.");
else puts ("Can't be divided.");
puts ("");
}
return 0;
}
多重背包代码//这个好理解一些
#include<bits/stdc++.h>
using namespace std;
const int mmax=50000;
int f[mmax],k[mmax],v[7]= {0,1,2,3,4,5,6},a[mmax];
int main()
{
int i,j,op;
for(op=1;;op++)
{
memset(f,0,sizeof(f));
int sum=0;
for(i=1; i<=6; i++)
{
scanf("%d",&k[i]);
sum+=k[i]*i;
v[i]=i;
}
if(sum==0)
break;
int hh=sum;
if(sum%2==1)
printf("Collection #%d:\nCan't be divided.\n\n",op);
int index=0;
if(sum%2==0&&hh!=0)
{
for(i=1; i<=6; i++)
{
for(j=1;j<=k[i];j*=2)
{
a[++index]=j*v[i];
k[i]-=j;
}
if(k[i]>0)
a[++index]=v[i]*k[i];
}
sum/=2;
for(i=1; i<=index; ++i)
{
for(j=sum; j>=a[i]; --j)
f[j]=max(f[j],f[j-a[i]]+a[i]);
}
if((hh-f[sum])!=sum)
printf("Collection #%d:\nCan't be divided.\n\n",op);
if((hh-f[sum])==sum)
printf("Collection #%d:\nCan be divided.\n\n",op);
}
}
return 0;
}
514




被折叠的 条评论
为什么被折叠?



