奇怪的电梯
#include<iostream>
using namespace std;
const int N=201;
int n,A,B;
int lift[N];
bool st[N];//每层楼最多去一次
int res=1e9;
void dfs(int x,int cnt)
{
if(x==B)
{
res=min(res,cnt);
return ;
}
if(x+lift[x]<=n&&!st[x])
{
st[x]=true;
dfs(x+lift[x],cnt+1);
st[x]=false;
}
if(x-lift[x]>0&&!st[x])
{
st[x]=true;
dfs(x-lift[x],cnt+1);
st[x]=false;
}
}
int main()
{
scanf("%d%d%d",&n,&A,&B);
for(int i=1;i<=n;i++)
{
scanf("%d",&lift[i]);
}
dfs(A,0);
printf("%d",res);
}
PERKET
#include<iostream>
#include<cmath>
using namespace std;
const int N=11;
int n;
int acid[N],bitter[N];
int st[N];//记录三种状态——未选、已选、未考虑
int res=1e9;
bool str;
void dfs(int x)
{
if(x==n)
{
int sum1=1,sum2=0;
for(int i=0;i<n;i++)
{
if(st[i]==1)
{
str=true;//防止没有数字进入
sum1*=acid[i];
sum2+=bitter[i];
}
}
if(str) res=min(res,abs(sum1-sum2));//导致res恒等于abs(sum1-sum2)
return ;
}
st[x]=2;//这里先未选,这样有好处就是字典序倒过来了,防止上面情况
dfs(x+1);
st[x]=0;
st[x]=1;
dfs(x+1);
st[x]=0;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&acid[i],&bitter[i]);
}
dfs(0);
printf("%d",res);
}
火柴棒的等式
//新版,更快
#include<iostream>
using namespace std;
const int N=10001;
int n;
int num[N]={6,2,5,5,4,5,6,3,7,6};//先将简单的0~9的棒数存入
int arr[N];
int res=0;
void dfs(int x,int ant)
{
if(ant>n-4) return ;
if(x>3)
{
if(arr[1]+arr[2]==arr[3]&&ant==n-4)
{
printf("%d + %d = %d\n",arr[1],arr[2],arr[3]);
res++;
}
return ;
}
for(int i=0;i<=1000;i++)
{
arr[x]=i;
dfs(x+1,ant+num[i]);
arr[x]=0;
}
}
int main()
{
scanf("%d",&n);
for(int i=10;i<1000;i++)//关键一步,不用一步一步递归,就已经算过的数可以重复使用
{
num[i]=num[i%10]+num[i/10];
}
dfs(1,0);
printf("%d",res);
}
/*
#include<iostream>
using namespace std;
const int N=10001;
int n;
int num[N]={6,2,5,5,4,5,6,3,7,6};//先将简单的0~9的棒数存入
int arr[N];
int res=0;
int col(int x)//通过已知的0~9推出接下来
{
if(num[x]) return num[x];
else
{
int sum=0;
while(x)
{
sum+=num[x%10];
x/=10;
}
return sum;
}
}
void dfs(int x,int ant)
{
if(ant>n-4) return ;
if(x>3)
{
if(arr[1]+arr[2]==arr[3]&&ant==n-4)
{
printf("%d + %d = %d\n",arr[1],arr[2],arr[3]);
res++;
}
return ;
}
for(int i=0;i<=1000;i++)
{
arr[x]=i;
dfs(x+1,ant+col(i));
arr[x]=0;
}
}
int main()
{
scanf("%d",&n);
dfs(1,0);
printf("%d",res);
}
*/
棋盘问题
#include<iostream>
using namespace std;
const int N=9;
char g[N][N];
int n,k;
bool st[N];
int res=0;
void dfs(int x,int y)
{
if(y==k)
{
res++;
return ;
}
if(x>=n) return ;
for(int i=0;i<n;i++)
{
if(g[x][i]=='#'&&!st[i])
{
st[i]=true;
dfs(x+1,y+1);
st[i]=false;
}
}
dfs(x+1,y);//关键,强制向下搜寻,防止漏
}
int main()
{
while(cin>>n>>k,n>0&&k>0)
{
for(int i=0;i<n;i++)
scanf("%s",g[i]);
res=0;
dfs(0,0);
printf("%d",res);
}
}
单词接龙
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
const int N=21;
int n;
string word[N];
char start;
int g[N][N];//g[i][j]记录第i个与第j个相连重合的数量
int used[N];//记录使用了几次
int res=0;
void dfs(string loong,int x)//loong是当前所处的大字符串,x是尾部单词第x个
{
res=max(res,(int)loong.size());
used[x]++;
for(int i=0;i<n;i++)
{
if(g[x][i]&&used[i]<2)//used[i]是连接后面的词+1
{
dfs(loong+word[i].substr(g[x][i]),i);
}
}
used[x]--;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
cin>>word[i];
}
cin>>start;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
string a=word[i],b=word[j];
for(int k=1;k<(int)min(a.size(),b.size());k++)//从1开始就没有包含
{
if(a.substr(a.size()-k,k)==b.substr(0,k))//判断重合部分,并且是最少部分,从后往前判断
{
g[i][j]=k;
break;
}
}
}
}
for(int i=0;i<n;i++)
{
if(start==word[i][0])
{
dfs(word[i],i);//不能break因为首字母可能有相同的
}
}
printf("%d",res);
}
Lake Counting S
#include<iostream>
#include<string>
using namespace std;
const int N=101;
int n,m;
string g[N];
int dx[]={1,-1,0,0,1,1,-1,-1},dy[]={0,0,-1,1,1,-1,1,-1};
int cnt=0;
void dfs(int x,int y)
{
for(int i=0;i<8;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<0||a>=n||b<0||b>=m||g[a][b]=='.') continue;
g[a][b]='.';
dfs(a,b);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
cin>>g[i];
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(g[i][j]!='.')
{
cnt++;
dfs(i,j);
}
}
printf("%d",cnt);
}