洛谷——【搜索】暴力专项训练

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。

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一道模拟题,题目描述如下: 有 n 个猴子,按顺序编号为 1,2,3,…,n。这 n 只猴子按顺序围成一圈。从第 1 只猴子开始数,数到第 m 只猴子,把它踢出圈,剩下的猴子重新围成一圈,继续从第 1 只猴子开始数,直到只剩下一只猴子为止。问最后剩下的猴子编号是多少? 下面是解题思路: 首先,我们可以用一个数组来表示每只猴子,用一个变量表示当前轮到的猴子的编号。每次数到第 m 只猴子,就将它从数组中删除(将它对应的元素置为 0),同时更新当前轮到的猴子的编号。如果数组中只剩下一只猴子,就输出它的编号。 具体实现可以参考下面的代码(C++实现): ``` #include <iostream> using namespace std; const int maxn = 10000; int a[maxn]; // 存储猴子编号的数组 int main() { int n, m; cin >> n >> m; for (int i = 0; i < n; i++) { a[i] = i + 1; // 初始化猴子编号 } int cur = 0; // 当前轮到的猴子的编号 while (true) { int cnt = 0; // 当前轮已经数了几只猴子 for (int i = 0; i < n; i++) { if (a[i] != 0) { // 如果这只猴子还没被踢出圈 cnt++; if (cnt == m) { // 数到了第 m 只猴子 a[i] = 0; // 踢出圈 cnt = 0; // 重新开始计数 } if (a[i] != 0) { cur = i; // 更新当前轮到的猴子的编号 } } } int sum = 0; // 统计剩下的猴子数量 int last = 0; // 记录最后一只猴子的编号 for (int i = 0; i < n; i++) { if (a[i] != 0) { sum++; last = a[i]; } } if (sum == 1) { // 只剩下一只猴子了 cout << last << endl; // 输出它的编号 break; // 结束循环 } } return 0; } ``` 希望能够帮助你解决这道题目

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值