zoukankan      html  css  js  c++  java
  • 洛谷题单 【算法17】搜索


    P1219 [USACO1.5]八皇后 Checker Challenge

    • PZ's solution:

      1.从每行开始搜索合法位置;

      2.寻找一个合法位置,符合 列、主对角线、次对角线 均未被标记;

      3.将此合法位置记录,将 列、主对角线、次对角线 标记;

      4.寻找下一个合法位置,直到\(n\)行为止 ,搜索完毕;

    绿色为列标号,记 \(lie[i]\)为列标记;

    红色为主对角线标号,记 \(zhu[i]\)为主对角线标记;

    蓝色为次对角线标号,记\(ci[i]\)为次对角线标记;

    观察\((1,1)\)位置,它在\(3\)号主对角线上。

    向右移动到\((1,2)\)位置,它就变为在\(2\)号主对角线上,可以确认 列标号与主对角线负相关;

    向下移动到\((2,1)\)位置,它就变为在\(4\)号主对角线上,可以确认 行标号与主对角线正相关;

    主对角线共\(2*n-1\)条,可以猜想到位置与主对角线标号互换关系为\((x,y) \to n-i+x\)

    同理,观察\((1,1)\)位置,它在\(1\)号次对角线上,

    向右移动到\((1,2)\)位置,它就变为在\(2\)号次对角线上,可以确认 列标号与次对角线正相关;

    向下移动到\((2,1)\)位置,它就变为在\(2\)号次对角线上,可以确认 行标号与次对角线正相关;

    次对角线共\(2*n-1\)条,可以猜想到 位置与次对角线标号互换关系为\((x,y) \to i+x-1\)

    • TAG:搜索;DFS深度优先搜索

    P1219.cpp

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,tot,ans[14],lie[14],zhu[25],ci[25];
    void dfs(int x){
    	if(x>n){
    		++tot;
    		if(tot<=3){
    			for(int i=1;i<=n;++i) printf("%d ",ans[i]);
    			putchar('\n');
    		}
    		return;
    	} else {
    		for(int i=1;i<=n;++i)
    			if(lie[i]==0 && ci[i+x-1]==0 && zhu[n-1-i+x]==0){
    				ans[x]=i;
    				lie[i]=ci[i+x-1]=zhu[n-1-i+x]=1;
    				dfs(x+1);
    				lie[i]=ci[i+x-1]=zhu[n-1-i+x]=0;
    			}
    	}
    }
    int main(){
    	scanf("%d",&n);
    	dfs(1);
    	printf("%d",tot);
    	return 0;
    }
    

    P2392 kkksc03考前临时抱佛脚

    • PZ's DFS solution:

      1.考虑\(DFS\) ,用两个变量作为左右脑进行搜索;

      2.每次都有两种选择,将当前题目交给左脑做,或者交给右脑做;

      3.直到做完 全部题目 ,比较左右脑谁的时间更多,时间多的则 与答案进行比较;

      4.由于递归的性质,所有情况都能被考虑到,\(DFS\)结束后即为最优答案;

    • PZ's DP solution:

      1.观察性质,最优状态一定是 左右脑的用时相等;

      2.考虑01背包,因为每道题只能做一次,设\(sum=\sum_{j=1}^{s_i}A_j\),将背包的上限设为\(\frac{sum}{2}\)

      考虑到 题目所消耗的时间,故可视为 物品的大小和价值 均为题目的时间,可得到状态转移方程:

      \[f[i]=max(f[i],f[i-A[j]+A[j]) \]

      3.因为可能有\(f[\frac{sum}{2}]\)凑不满的情况,显然有 \(sum-f[\frac{sum}{2}] \ge f[\frac{sum}{2}]\),故在累加答案时有\(ans=sum-f[\frac{sum}{2}]\)

    • TAG:搜索;DFS深度优先搜索;DP动态规划;背包;01背包

    P2392 DFS.cpp

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    //使用 INT_MAX 需要 使用#include<climits>头文件 
    using namespace std;
    int s[5],a[5][21],totr,totl,res,ans;
    bool vis[5][21];
    void dfs(int k,int x){
    	if(x>s[k]){
    		res=min(res,max(totl,totr));
    		return;
    	} else {
    		totl+=a[k][x];
    		dfs(k,x+1);
    		totl-=a[k][x];
    		totr+=a[k][x];
    		dfs(k,x+1);
    		totr-=a[k][x];
    	}
    }
    int main(){
    	for(int i=1;i<=4;++i) scanf("%d",&s[i]);
    	for(int i=1;i<=4;++i){
    		res=INT_MAX; totl=totr=0;
    		for(int j=1;j<=s[i];++j) scanf("%d",&a[i][j]);
    		dfs(i,1);
    		ans+=res;
    	}
    	printf("%d",ans);
    	return 0;
    }
    

    P2392 DP.cpp

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int s[5],a[65],f[1205],ans,sum;
    int main(){
    	for(int i=1;i<=4;++i) scanf("%d",&s[i]);
    	for(int i=1;i<=4;++i){
    		sum=0;
    		memset(f,0,sizeof(f));
    		for(int j=1;j<=s[i];++j){ scanf("%d",&a[j]); sum+=a[j]; }
    		for(int j=1;j<=s[i];++j)
    			for(int k=sum/2;k>=a[j];--k)
    				f[k]=max(f[k],f[k-a[j]]+a[j]);
    		ans+=sum-f[sum/2];
    	}
    	printf("%d",ans);
    	return 0;
    }
    

    P1443 马的遍历

    • TAG:搜索;BFS广度优先搜索

      广搜的模板题,注意马走日即可;

      值得注意的一点:若视边权为\(1\),广搜时 每遍历到一个点,到达它的步数 即为 到达此处的最短路权

    P1443.cpp

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    int fx[]={2,2,-2,-2,1,1,-1,-1};
    int fy[]={1,-1,1,-1,2,-2,2,-2};
    int s[4000][4000],n,m,x,y;
    void bfs(int x,int y){
    	memset(s,-1,sizeof(s));
    	queue<int>qx; queue<int>qy;
    	qx.push(x); qy.push(y); s[x][y]=0;
    	while(!qx.empty()){
    		x=qx.front(); y=qy.front(); qx.pop(); qy.pop();
    		for(int nx,ny,i=0;i<8;++i){
    			nx=x+fx[i]; ny=y+fy[i];
    			if(nx>0&&nx<=n&&ny>0&&ny<=m&&s[nx][ny]==-1){
    				s[nx][ny]=s[x][y]+1;
    				qx.push(nx); qy.push(ny);
    			}
    		}
    	}
    }
    int main(){
    	scanf("%d %d %d %d",&n,&m,&x,&y);
    	bfs(x,y);
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=m;++j)
    			printf("%-5d",s[i][j]);
    		puts("");
    	}
    	return 0;
    }
    

    P1135 奇怪的电梯

  • 相关阅读:
    JFinal Web开发学习(二)目录、架构、package设计
    JFinal Web开发学习(一)开启HelloWorld
    使用JFinal实现使用MVC获取表单中的数据并将提示信息返回给另一jsp页面。
    [JSOI2010]满汉全席 -- 2-SAT
    [HNOI/AHOI2018] 道路
    ZJOI2006 物流运输
    HNOI2005 狡猾的商人
    打上标记(给树)
    hdu-6201
    Wannfly day2 采蘑菇
  • 原文地址:https://www.cnblogs.com/Potrem/p/Luogu_algorithm_1_7.html
Copyright © 2011-2022 走看看