P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins
每种饲料只能用一次,因此我们要遍历每一种情况。即对于饲料,我们可以选择取也可以选择不取,在合适的情况下进行判断,若小于则更新数据。
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define YES puts("YES");
#define NO puts("NO");
#define all(a) begin(a), end(a)
#define x first
#define y second
#define pb(x) push_back(x)
typedef long long ll;
typedef pair<int,int> PII;
const int N=2e5+10;
int t,n,m,ans,minn=1000;
int v[N],b[30][30],c[N],d[N];
bool jud(int cnt)
{
for(int i=1;i<=n;i++)
{
int s=0;
for(int j=1;j<=cnt;j++)
{
s+=b[c[j]][i];
}
if(s<v[i])return false;
}
return true;
}
void dfs(int u,int cnt)
{
if(jud(cnt))
{
if(cnt<minn)
{
minn=cnt;
for(int i=1;i<=cnt;i++)
{
d[i]=c[i];
}
}
}
if(u>m)return ;
c[cnt+1]=u;
dfs(u+1,cnt+1);
c[cnt+1]=0;
dfs(u+1,cnt);
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>v[i];
}
cin>>m;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
cin>>b[i][j];
}
}
dfs(1,0);
cout<<minn;
for(int i=1;i<=minn;i++)
{
cout<<" "<<d[i];
}
return 0;
}
P1294 高手去散步
和上一题一样,遍历每一次可能的路程,计算最长的路程并保存。
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define YES puts("YES");
#define NO puts("NO");
#define all(a) begin(a), end(a)
#define x first
#define y second
#define pb(x) push_back(x)
typedef long long ll;
typedef pair<int,int> PII;
const int N=100;
int t,n,m,ans,minn=1000;
int e[N],w[N],ne[N],h[N],idx;
bool st[N];
void add(int a,int b,int c)
{
e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}
void dfs(int u,int s)
{
if(s>ans)ans=s;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j])
{
st[j]=true;
dfs(j,s+w[i]);//???
st[j]=false;
}
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
memset(h,-1,sizeof h);
cin>>n>>m;
int a,b,c;
for(int i=1;i<=m;i++)
{
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
}
for(int i=1;i<=n;i++)
{
st[i]=true;
dfs(i,0);
st[i]=false;
}
cout<<ans;
return 0;
}
P1123 取数游戏
依旧还是考虑怎么遍历每一种情况,在这里搜索顺序很重要, 我们可以先遍历第一行,走到底之后遍历第二行,在能取该数的情况下,考虑取数和不取两种情况。
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define YES puts("YES");
#define NO puts("NO");
#define all(a) begin(a), end(a)
#define pb(x) push_back(x)
typedef long long ll;
typedef pair<int,int> PII;
const int N=100;
int t,n,m,ans,minn=1000,s;
int g[10][10];
int dx[8]={-1,-1,-1,0,0,1,1,1},dy[8]={-1,0,1,-1,1,-1,0,1};
int st[10][10];
void dfs(int x,int y)
{
ans=max(s,ans);
if(y==m+1)
{
dfs(x+1,1);return ;
}
if(x==n+1)//***
{
return;
}
dfs(x,y+1);
if(st[x][y]==false)
{
s+=g[x][y];
for(int i=0;i<8;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<1||a>n||b<1||b>m)continue;
st[a][b]++;
}
dfs(x,y+1);
for(int i=0;i<8;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<1||a>n||b<1||b>m)continue;
st[a][b]--;
}
s-=g[x][y];
}
}
void solve()
{
ans=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>g[i][j];
dfs(1,1);
cout<<ans<<endl;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>t;
while(t--)
{
solve();
}
return 0;
}
Maze
这个题目很好的解释了DFS在处理连通性问题上的应用,为了不破坏连通性,所以我们要在最末端打上‘X’。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 550;
int n,m,k,cnt;
char g[N][N];
bool st[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void dfs(int x,int y)
{
st[x][y]=true;
for (int i = 0; i < 4; i ++ )
{
int a=x+dx[i],b=y+dy[i];
if(a<=0||a>n||b<=0||b>m)continue;
if(g[a][b]=='#'||st[a][b])continue;
dfs(a,b);
if(cnt<k)
{
g[a][b]='X';
cnt++;
}
}
}
int main()
{
cin>>n>>m>>k;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
cin>>g[i][j];
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
{
if(g[i][j]=='.')
{
dfs(i,j);
//if(cnt==k-1)g[i][j]='X';
break;
}
}
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ )
cout<<g[i][j];
puts("");
}
return 0;
}
Smallest number
我们考虑怎么遍历每一种情况, 每次的运算是固定的,所以我们要每次取出不同的数字来运算。
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define YES puts("YES");
#define NO puts("NO");
#define all(a) begin(a), end(a)
#define pb(x) push_back(x)
typedef long long ll;
typedef pair<int,int> PII;
const int N=100;
int t,n,m;
ll a[4],ans=1e12+10;
char b[3];
bool st[4];
void dfs(int u)
{
if(u==3)
{
for(int i=0;i<4;i++)
{
if(!st[i])
ans=min(ans,a[i]);
}
return ;//
}
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(i==j||st[i]||st[j])continue;
int t=a[i];
if(b[u]=='+')
a[i]+=a[j];
else
a[i]*=a[j];
st[j]=true;
dfs(u+1);
st[j]=false;
a[i]=t;
}
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
for(int i=0;i<4;i++)cin>>a[i];
for(int i=0;i<3;i++)cin>>b[i];
dfs(0);
cout<<ans<<endl;
return 0;
}
P1025 [NOIP2001 提高组] 数的划分
如果我们要用到上次使用的数据,那么在dfs中加入last。
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define YES puts("YES");
#define NO puts("NO");
#define all(a) begin(a), end(a)
#define pb(x) push_back(x)
typedef long long ll;
typedef pair<int,int> PII;
const int N=100;
int t,n,m,ans;
void dfs(int last,int u,int s)
{
if(u==m)
{
if(s==n)ans++;
return;
}
for(int i=last;s+i*(m-u)<=n;i++)//***
{
dfs(i,u+1,s+i);
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m;
dfs(1,0,0);
cout<<ans;
return 0;
}
注意点
1.边界的判定:如果是dfs(1,1)开始的话,结束的判断条件一般是x==n+1,y==m+1。