ACM 暴力搜索题 题目整理

UVa 129 Krypton Factor

注意输出格式,比较坑爹。

每次要进行处理去掉容易的串,统计困难串的个数。

#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<string>
#define INF 1000000000LL
#define ll long long
using namespace std;
char str[100];
int cnt,K,L;
bool check(int len)
{
    int l=strlen(str);
    if(l==0||l==1) return false;
    for(int i=1; i<=len/2; ++i)
    {
        bool ok=true;
        for(int j=0; j<i&&ok; ++j)
        {
            if(str[len-1-j]!=str[len-1-i-j])
                ok=false;
        }
        if(ok) return true;
    }
    return false;
}
void dfs(int pos)
{
    if(cnt>=K) return ;
    else
    {
        for(int i=0; i<L; ++i)
        {
            str[pos]=‘A‘+i;
            str[pos+1]=0;
            if(!check(pos+1)) cnt++;
            else continue ;
            dfs(pos+1);
            if(cnt>=K) return ;
        }
    }
}
int main()
{
    while(scanf("%d%d",&K,&L)!=EOF)
    {
        if(!K&&!L) break;
        cnt=0;
        dfs(0);
        int L=strlen(str);
        for(int i=0; str[i]; ++i)
        {
            if(i&&i%4==0&&i%64) putchar(‘ ‘);
            putchar(str[i]);
            if((i+1)%64==0) putchar(‘\n‘);
        }
        if(L%64) putchar(‘\n‘);
        printf("%d\n",L);
    }
    return 0;
}

SPOJ COMCB  1003

注意棋盘方格总数不会超过26。所以可以尝试dfs回溯寻找最优解。

怎么找字典序最小的,这个把棋盘画出来,然后指定一下每次跳的方向的顺序就行。如果第一个跳完全部棋盘的就是最优解。

这里要求输出最优解,每个位置是二维的,可以把它们压缩成一维,开一个数组,下标存第几步,内容存位置,这样就方便储存了。

实际上可行解并不多,可以打表。

HDU 4848 Wow! Such Conquering!

首先用fylod求最短路,然后搜索。时间复杂度大约是30!。肯定要剪枝。

有两个剪枝,一个是如果当前时刻有星球永远无法到达,则return,另一个是如果到该星球以后的时间花费比当前最优解要小则剪枝。这样就能过了。

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf 100000000
using namespace std;
int dist[35][35],tim[35];
int n;
int ans;
bool vis[35];
void dfs(int now,int rest,int all,int sum)
{
    if(all>=ans) return ;
    if(rest==0)
    {
        ans=min(ans,all);
        return ;
    }
    for(int i=1; i<n; ++i)
        if((!vis[i])&&(sum+dist[now][i]>tim[i]))
            return;
    for(int i=1; i<n; ++i)
    {
        if(!vis[i])
        {
            int time=sum+dist[now][i];
            if(time<=tim[i])
            {
                if(ans<=all+rest*time) continue;
                vis[i]=true;
                dfs(i,rest-1,all+time,time);
                vis[i]=false;
            }
        }
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0; i<n; ++i)
            for(int j=0; j<n; ++j)
            {
                scanf("%d",&dist[i][j]);
            }
        for(int k=0; k<n; ++k)
            for(int i=0; i<n; ++i)
                for(int j=0; j<n; ++j)
                    dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
        for(int i=1; i<n; ++i)
        {
            scanf("%d",&tim[i]);
        }
        ans=inf;
        memset(vis,0,sizeof(vis));
        vis[0]=true;
        dfs(0,n-1,0,0);
        if(ans==inf) puts("-1");
        else printf("%d\n",ans);
    }
    return 0;
}

SGU 125  Shtirlits

给一个矩阵B,每个元素B[i][j]表示A[i][j]上下左右四周有多少个数大于自身。输出一个可能的矩阵A。

由于n<=3,完全可以暴力搜索解决。但是9^9肯定会超时的,考虑剪枝。对于每个A[i][j]枚举可能的元素,当枚举到第二行以上的时候,该元素上面的一个元素四周的元素都已经确定了,可以判断是否满足题意,不满足则剪枝。当枚举到最后一行的时候,还可以判断左边的元素是否满足题意。当所有元素都枚举完毕,要进行一次全体的判断,如果符合就是答案。

之前想到一个剪枝,以为每次枚举A[i][j],可以从0枚举到9-B[i][j]。其实这是不对的,因为比A[i][j]大的元素可能是相同的。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int B[4][4];
int A[4][4];
int n;
bool judge(int x,int y)
{
    return 0<=x&&x<n&&0<=y&&y<n;
}
const int Move[4][2]= {{-1,0},{0,-1},{1,0},{0,1}};
bool check(int x,int y)
{
    int cnt=0;
    for(int i=0; i<4; ++i)
    {
        int nx=x+Move[i][0],ny=y+Move[i][1];
        if(judge(nx,ny))
        {
            if(A[x][y]<A[nx][ny])
                cnt++;
        }
    }
    return cnt==B[x][y];
}
bool dfs(int cur)
{
    if(cur==n*n)
    {
         for(int i=0;i<n;++i)
            for(int j=0;j<n;++j)
            if(!check(i,j)) return false;
         return true;
    }
    const int x=cur/n,y=cur%n;
    for(int i=0; i<=9; ++i)
    {
        A[x][y]=i;
        if((x>=1&&!check(x-1,y))||(x==n-1&&y>=1&&!check(x,y-1)))
            continue;
        if(dfs(cur+1))
            return true;
    }
    return false;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0; i<n; ++i)
            for(int j=0; j<n; ++j)
                scanf("%d",&B[i][j]);
        if(!dfs(0))
            puts("NO SOLUTION");
        else
        {
            for(int i=0; i<n; ++i)
            {
                for(int j=0; j<n; ++j)
                    if(!j) printf("%d",A[i][j]);
                    else printf(" %d",A[i][j]);
                printf("\n");
            }
        }
    }
    return 0;
}

ACM 暴力搜索题 题目整理,布布扣,bubuko.com

时间: 2024-10-06 19:11:59

ACM 暴力搜索题 题目整理的相关文章

ACM 矩阵题目整理

先从最基础的矩阵快速幂加速递推开始. HDU 1005 Number Sequence |f[n-2],f[n-1]|* |0 B| =|f[n-1], B*f[n-2]+A*f[n-1]|=|f[n-1],f[n]|   |1 A| 建立矩阵如上然后利用快速幂求解即可.答案是mat[0][1]. #include<iostream> #include<vector> #include<cmath> #include<map> #include<alg

ACM 字符串 题目整理

AC自动机 UVa 11468  Substring AC自动机+概率DP. 注意要补全不存在的边. 为什么要补全不存在的边呢?补全以后可以直接找到状态的转移,即从所有子节点就可以实现所有状态转移. #include<iostream> #include<vector> #include<cmath> #include<map> #include<algorithm> #include<cstring> #include<cst

搜索题推荐

(转自网络博客): POJ POJ 1376 – Robot(基础) http://acm.pku.edu.cn/JudgeOnline/problem?id=1376 题意:略 解法:bfs,A*-. POJ 2688 – Cleaning Robot(基础) http://acm.pku.edu.cn/JudgeOnline/problem?id=2688 题意:bfs后转换为tsp问题 解法:bfs+dp,bfs+dfs 相关:http://hi.baidu.com/zfy0701/blo

[暴力搜索] POJ 3087 Shuffle&#39;m Up

Shuffle'm Up Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10003   Accepted: 4631 Description A common pastime for poker players at a poker table is to shuffle stacks of chips. Shuffling chips is performed by starting with two stacks o

hdu 1399 Starship Hakodate-maru (暴力搜索)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1399 题目大意:找到满足i*i*i+j*(j+1)*(j+2)/6形式且小于等于n的最大值. 1 #include<iostream> 2 #include<cstdio> 3 4 using namespace std; 5 6 int main() 7 { 8 int n; 9 while(scanf("%d",&n),n) 10 { 11 int j,

ACM训练方案-POJ题目分类

ACM训练方案-POJ题目分类 博客分类: 算法 ACM online Judge 中国: 浙江大学(ZJU):http://acm.zju.edu.cn/ 北京大学(PKU):http://acm.pku.edu.cn/JudgeOnline/ 杭州电子科技大学(HDU):http://acm.hdu.edu.cn/ 中国科技大学(USTC):http://acm.ustc.edu.cn/ 北京航天航空大学(BUAA)http://acm.buaa.edu.cn/oj/index.php 南京

50题(ACM学习推荐题)

POJ推荐50题 1. 标记"难"和"稍难"的题目可以看看,思考一下,不做要求,当然有能力的同学可以直接切掉. 2. 标记为 A and B 的题目是比较相似的题目,建议大家两个一起做,可以对比总结,且二者算作一个题目. 3. 列表中大约有70个题目.大家选做其中的50道,且每类题目有最低数量限制. 4. 这里不少题目在 BUPT ACM FTP 上面都有代码,请大家合理利用资源. 5. 50个题目要求每个题目都要写总结,养成良好的习惯. 9. 这个列表的目的在于让

11214 - Guarding the Chessboard(暴力搜索)

IDA*算法, 从小到大枚举深度上限,不过该题是有深度上限的,题目中的第一个样例表明:最多需要5个皇后就可以覆盖整个棋盘 . 利用紫书上的技巧,我们可以快速的判断任意两个棋子是不是在同一行.同一列.同一对角线 (详情见紫书P193那两个图). 这样之后暴力搜索就可以了 . 每一层需要O(nm)的复杂度,但是实际上并不需要那么大的复杂度 .和八皇后问题类似 , 当前行之前的行已经放置了皇后,所以不必在管,每次从下一行开始放置就好 . 细节见代码: #include<bits/stdc++.h>

hdu 4770 Lights Against Dudely 暴力搜索

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4770 题目大意是让你放一些灯照亮一些房间 灯不可以照到某些特殊房间 但可以照出边界 灯光必须覆盖所有可以放灯的房间 求至少需要多少灯 搜索题 应该注意到冗长而无聊的题面中有告诉你最多只有15个可以放灯的房间 所以2^15来枚举 还应该注意到冗长而无聊的题面中有告诉你最多只有1个灯可以转向 所以还应该枚举哪个灯来转向 转向再枚举4个方向 然后判断是否成立 为了简化问题 单独把那些可放灯空间拿出来 最多