洛谷题单_搜索

P1219 [USACO1.5] 八皇后 Checker Challenge - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <bits/stdc++.h>
using namespace std;
const int N=14;
int n,ans=0;
int a[N][N]={},vis[N][N]={};
vector<int>rcd(n+1);
void dfs(int dep){
    if(dep==n+1){
        if(ans<=2){for(int i=1;i<=n;i++)cout<<rcd[i]<<" \n"[i==n];}
        ans++;return ;
    }//此时该搜索第n+1行说明前n行已经排列完成了 
    for(int i=1;i<=n;i++){
        if(vis[dep][i])continue;//如果出现过就直接跳过
        rcd[dep]=i;
        for(int _i=1;_i<=n;_i++)vis[_i][i]++;//这一列都是0
        for(int _i=dep,_j=i;_i>=1&&_j>=1;--_i,--_j)vis[_i][_j]++;//左上
        for(int _i=dep,_j=i;_i>=1&&_j<=n;--_i,++_j)vis[_i][_j]++;//右上
        for(int _i=dep,_j=i;_i<=n&&_j<=n;++_i,++_j)vis[_i][_j]++;//右下
        for(int _i=dep,_j=i;_i<=n&&_j>=1;++_i,--_j)vis[_i][_j]++;//左下
        dfs(dep+1);//搜索下一行
        //回溯
        for(int _i=1;_i<=n;_i++)vis[_i][i]--;//这一列都是0
        for(int _i=dep,_j=i;_i>=1&&_j>=1;--_i,--_j)vis[_i][_j]--;//左上
        for(int _i=dep,_j=i;_i>=1&&_j<=n;--_i,++_j)vis[_i][_j]--;//右上
        for(int _i=dep,_j=i;_i<=n&&_j<=n;++_i,++_j)vis[_i][_j]--;//右下
        for(int _i=dep,_j=i;_i<=n&&_j>=1;++_i,--_j)vis[_i][_j]--;//左下
    }
}
int main(){
    cin>>n;
    dfs(1);//从第一行开始搜索
    cout<<ans;
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N=16;
int a[N];//表示第i行皇后放在a[i]列
int n,cnt;
// int vis[N][N];
vector<int>ans;
int nd=3;
bool check(int x){//输入行,不与每一行的皇后成关系就行
//检查x行 a[x]列的皇后是否可以放
    for(int i=1;i<x;i++){//遍历之前的所有行
        if(a[i]==a[x]||a[i]-i==a[x]-x||a[x]+x==a[i]+i)return 0;
    }//主对角线行-列=行-列 副对角线上行+列=行+列
//若位于同一列 或位于同一主对角线上或者位于同一副对角线上就不行
    return 1;
}
void dfs(int dep){
    if(dep==n+1){
        cnt++;//该搜索第n+1行了就说明前n行已经拍好了
        if(nd-->0){
            for(int i=0;i<n;i++){
                cout<<ans[i]<<" \n"[i==n-1];
            }
        }
        return ;
    }
    for(int i=1;i<=n;i++){
        a[dep]=i;//遍历假设放在了(dep,a[dep])位置
        if(!check(dep))continue;//如果不行 跳
        ans.push_back(i);//存起来放在了第i列
        dfs(dep+1);//搜索下一行
        ans.pop_back();//回溯
        a[dep]=0;//数组的a[dep]按理也得恢复现场
    }
    
}
int main(){
    cin>>n;
    dfs(1);
    cout<<cnt;
    return 0;
}

 P2392 kkksc03考前临时抱佛脚 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
using namespace std;
int a[5],i,j,k,sum,t,homework[21],dp[2501];
//dp[j]表示只考虑前面几个商品 在总时间为j的条件下所能得到的最大价值(最大时间)
int main(){
	for(i=1;i<=4;i++)cin>>a[i];
	for(i=1;i<=4;i++){
		sum=0;	
		for(j=1;j<=a[i];j++)
			{cin>>homework[j];//输入
			sum+=homework[j];}//总时间累加
//最快洗车时间的问题
		for(j=1;j<=a[i];j++)
			for(k=sum/2;k>=homework[j];k--)//只要是总和的一半
				dp[k]=max(dp[k],dp[k-homework[j]]+homework[j]);//01背包
		t+=sum-dp[sum/2];//累加为另一个脑子
		memset(dp,0,sizeof(dp));
	}
	cout<<t;//输出
	return 0;
}

 P1443 马的遍历 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <bits/stdc++.h>
#define int long long
#define PII pair<int,int>
using namespace std;
const int N=406;
int xx[]={2,2,-2,-2,1,-1,1,-1};
int yy[]={1,-1,-1,1,2,-2,-2,2};//八个方向
int mp[N][N];int cnt=0;int n,m;

void bfs(int x,int y,int c){//广度优先搜索模板
    queue<PII>q;
    q.push({x,y});
    mp[x][y]=c;
    while(!q.empty()){
        auto cur=q.front();
        q.pop();
        int cx=cur.first;
        int cy=cur.second;
        for(int i=0;i<8;i++){
            int tx=cx+xx[i];
            int ty=cy+yy[i];
            if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&mp[tx][ty]==-1){
                mp[tx][ty]=mp[cx][cy]+1;//从上一个的转移一次 所以要在上一次的基础上+1
                q.push({tx,ty});
            }
        }
    }
}

void solve(){
    cin>>n>>m;
    int x,y;cin>>x>>y;
    memset(mp, -1, sizeof(mp));
    // mp[x][y]=0;
    bfs(x,y,0);
    for(int i=1;i<=n;i++){//一定要看好时从(0,0)开始还是从(1,1)开始
        for(int j=1;j<=m;j++){
            printf("%-5d",mp[i][j]);
    //-5是每一行开头的那个元素不产生占位5 4 3 2 这样
    //5是每一行从开头就产生占位 5 4 3 2这样
        }
        cout<<'\n';
    }
}

signed main(){
    int t=1;
    while(t--)solve();
    return 0;
}
#include <iostream>
#include <queue>
using namespace std;
int k[205], n; // k[i] 表示在i楼能向上或向下走多少步

struct node { // 定义一个结构体
	int point, step; // point是现在在哪一楼,step是现在点了几次按钮到达这一楼
};

bool vis[205]; // 记录之前是否到达过(或者可以到达)这个楼数,那么下一次的统计的步数肯定大于等于这一楼记录过的最少步数,不更新这一楼的答案。

int BFS(int a, int b) {
	queue < node > q;
	q.push(node{a, 0});
	while (q.size()) { // 队列里还有元素就用队头元素尝试更新
		node p = q.front();
		if (p.point == b) { // 到了目标楼层
			return p.step; // 返回步数
		}
		q.pop();
		if (p.point + k[p.point] >= 1 && p.point + k[p.point] <= n && ! vis[p.point + k[p.point]]) { // 往上走,符合条件(在1~n层之间)且没被访问过(说明是第一次入队,也就是这次被访问就是最短的步数)
			q.push((node){p.point + k[p.point], p.step + 1});
			vis[p.point + k[p.point]] = 1;
		}
		if (p.point - k[p.point] >= 1 && p.point - k[p.point] <= n && ! vis[p.point - k[p.point]]) { // 往下走
			q.push((node){p.point - k[p.point], p.step + 1});
			vis[p.point - k[p.point]] = 1;
		}
	}
	return -1; // 无解
}

int main() {
	int a, b;
	cin >> n >> a >> b;
	for (int i = 1; i <= n; i++) cin >> k[i];//每个电梯的能量值
	cout << BFS(a, b);
}

P1135 奇怪的电梯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 

#include <iostream>
#include <queue>
using namespace std;
int k[205], n; // k[i] 表示在i楼能向上或向下走多少步

struct node { // 定义一个结构体
	int point, step; // point是现在在哪一楼,step是现在点了几次按钮到达这一楼
};

bool vis[205]; // 记录之前是否到达过(或者可以到达)这个楼数,那么下一次的统计的步数肯定大于等于这一楼记录过的最少步数,不更新这一楼的答案。

int BFS(int a, int b) {
	queue < node > q;
	q.push(node{a, 0});
	while (q.size()) { // 队列里还有元素就用队头元素尝试更新
		node p = q.front();
		if (p.point == b) { // 到了目标楼层
			return p.step; // 返回步数
		}
		q.pop();
		if (p.point + k[p.point] >= 1 && p.point + k[p.point] <= n && ! vis[p.point + k[p.point]]) { // 往上走,符合条件(在1~n层之间)且没被访问过(说明是第一次入队,也就是这次被访问就是最短的步数)
			q.push((node){p.point + k[p.point], p.step + 1});
			vis[p.point + k[p.point]] = 1;
		}
		if (p.point - k[p.point] >= 1 && p.point - k[p.point] <= n && ! vis[p.point - k[p.point]]) { // 往下走
			q.push((node){p.point - k[p.point], p.step + 1});
			vis[p.point - k[p.point]] = 1;
		}
	}
	return -1; // 无解
}

int main() {
	int a, b;
	cin >> n >> a >> b;
	for (int i = 1; i <= n; i++) cin >> k[i];
	cout << BFS(a, b);
}

P2895 [USACO08FEB] Meteor Shower S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 

P1036 [NOIP2002 普及组] 选数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <bits/stdc++.h>
using namespace std;
int n,k;
const int N=26;
int a[N],vis[N]={0};
int ans=0;
typedef long long ll;
bool isprime(int x){
    for(int i=2;i<=x/i;i++){
        if(x%i==0)return 0;
    }
    return 1;
}
void dfs(int m, int sum, int startx){//最重要的递归
//m代表现在选择了多少个数
//sum表示当前的和
//startx表示升序排列,以免算重
    if(m == k){//如果选完了的话
        if(isprime(sum))ans++;//ans加一
        return ;
    }
    for(int i = startx; i < n; i++)//往后找
        dfs(m + 1, sum + a[i], i + 1);//递归
        //步数要加一,和也要加
        //升序起始值要变成i+1,以免算重
    return ;//这一个步骤下,所有的都枚举完了
    //直接返回去
}
int main(){
    scanf("%d%d",&n,&k);//输入
    for(int i = 0; i < n; i++)scanf("%d",&a[i]);//循环读入
    dfs(0,0,0);//调用函数
    printf("%d\n",ans);//输出答案
    return 0;//结束程序
}
//另一种思路错的原因是因为可能出现 1 2 1 1 3 6 7这样的情况

P2036 [COCI2008-2009 #2] PERKET - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 

#include<bits/stdc++.h>		//非常稳健的万能头
using namespace std;
long long int s[20],b[20],f[20];	//s表示酸度,b表示甜度,f记录是否查找
long long int n,j,c=1,y=0,ans=99999999999;		//ans记录最小值
void dfs(int x){
	if(x>n)return ;		//最多选n种调料,超过不做操作
		for(int i=1;i<=n;i++)
		{
			if(f[i]==0)		//没有查找过的才操作
			{
				c*=s[i];
				y+=b[i];
				ans=min(ans,abs(c-y));	//取最小值
				f[i]=1;		//记录
				dfs(x+1);
				f[i]=0;		//回溯
				c/=s[i];
				y-=b[i];
		}
	}
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>s[i]>>b[i];
	}
	dfs(1);
	cout<<ans;
}

 

#include <btis/stdc++.h>
using namespace std;
int a[15],b[15],n,ans=1<<30; //a表示酸度,b表示甜度,ans为最终答案。
void dfs(int i,int sj,int th){
    if(i>n){
        if(!th)return ; //如果没有选任何一种材料。
        ans=min(ans,abs(sj-th)); //否则更新答案。
        return ;
    }
    dfs(i+1,sj,th); //选
    dfs(i+1,sj*a[i],th+b[i]); //不选
}
int main(){
    int i;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d %d",&a[i],&b[i]);
    dfs(1,1,0);  //搜索,注意酸度初始值一定为1,甜度初始值一定为0.
    printf("%d",ans);
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值