简单搜索&&进阶搜索题解(1) java学习日志(1)

目录

简单搜索&&进阶搜索

A - Dungeon Master

B - Fliptile

C - Find The Multiple

D - Shuffle'm Up

J - 哈密顿绕行世界问题

Java学习日志


A - Dungeon Master
思路:
三维的广度优先搜索,自需在方向上添加向上和向下+额外判断高度是否越界,其余同二维

#include
#include
using namespace std;
const int maxn = 35;
int l, n, m;
int vis[maxn][maxn][maxn];   //标记
char mp[maxn][maxn][maxn];      //存图
int dir[6][3] = { {1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1} };   //方向
struct node
{
    int x, y, z, t;
    node() {}
    node(int zz, int xx, int yy, int tt) {
        x = xx, y = yy, z = zz, t = tt;
    }
};
void bfs(node s, node e)
{
    bool flag = true;
    queueq;
    q.push(node(s.z, s.x, s.y, s.t));
    while (!q.empty()) {
        node a = q.front();
        q.pop();
        for (int i = 0; i < 6; i++) {
            int zz = a.z + dir[i][0];
            int xx = a.x + dir[i][1];
            int yy = a.y + dir[i][2];
            if (zz >= 0 && zz < l && xx >= 0 && xx < n && yy >= 0 && yy < m && (!vis[zz][xx][yy]) && mp[zz][xx][yy] != '#') {
                q.push(node(zz, xx, yy, (a.t + 1)));
                vis[zz][xx][yy] = 1;
                if (zz == e.z && xx == e.x && yy == e.y) {
                    cout<<"Escaped in "<> l >> n >> m;
    while (l + n + m) {
        node s, e;
        memset(vis, 0, sizeof(vis));
        for (int k = 0; k < l; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    cin >> mp[k][i][j];
                    if (mp[k][i][j] == 'S') {
                        s.z = k,s.x = i,s.y = j,s.t = 0;
                    }
                    if (mp[k][i][j] == 'E') {
                        e.z = k, e.x = i, e.y = j, e.t = 0;
                    }
                }
            }
        }
        bfs(s, e);
        cin >> l >> n >> m;
    }

    return 0;
}


B - Fliptile
思路:贪心+用状态压缩(二进制枚举第一列所有的情况),因为只能影响周围一格的情况,所以可以用第二行翻转第一行全为0,
...一直到最后一行,判断最后一行是否全为0即可,
上一行(x,y)是1需要翻转,于是判断(x,y)是否为1是关键,因为翻转只能由周围和自身决定,
所以只需记录周围及自身操作了多少次,从而得出被反转多少次

#include
using namespace std;
const int maxn = 20;
int Min = 0x3f3f3f3f;
int n, m;
int mp[maxn][maxn];
int maap[maxn][maxn];
int p[maxn][maxn];
int dir[5][2] = { {0,0},{1,0},{0,1},{-1,0},{0,-1} };
bool in(int x,int y) {    //判断越界
    return x <= n && x >= 1 && y <= m && y >= 1;
}
bool judge(int x,int y) {
    int cnt = mp[x][y];           //初始值
    for (int i = 0; i < 5; i++) {
        int tx = x + dir[i][0];
        int ty = y + dir[i][1];
        if (in(tx, ty))
            cnt += maap[tx][ty];
    }
    return cnt % 2;            //翻转奇数后为1,偶数为0
}
int dfs()
{
    for (int i = 2; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (judge(i - 1, j))          //上一行为1的进行翻转
                maap[i][j] = 1;
        }
    }
    for (int i = 1; i <= m; i++) {
        if (judge(n, i))                         //最后一行有1的情况,返回无穷大表示不可取
            return 0x3f3f3f3f;
    }
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cnt += maap[i][j];
        }
    }
    return cnt;
}
int main()
{
    ios::sync_with_stdio(false);
    cin >> n>> m;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> mp[i][j];
        }
    }
    for (int i = 0; i < (1 << m); i++) {   //枚举第一行所有情况
        memset(maap, 0, sizeof(maap));
        for (int j = 1; j <= m; j++) {
            maap[1][m - j + 1] = (i >> (j - 1)) & 1;
        }
        int ans=dfs();
        if (ans < Min) {
            Min = ans;
            memcpy(p, maap, sizeof(p));     //memcpy函数的使用
        }
    }
    if (Min == 0x3f3f3f3f)
        cout << "IMPOSSIBLE" << '\n';
    else {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                cout << p[i][j] << ' ';
            }
            cout << '\n';
        }
    }
    return 0;
}


C - Find The Multiple
long long 的数据范围-922 3372 0368 5477 5808 ~ 922 3372 0368 5477 5807最多23位
时间超限(错解)

#include
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    int n;
    while (cin >> n&&n) {
        for (int i = 1; i < (1 << 23); i++) {
            bool flag = 0;
            int x = i;
            while (x) {
                if (x % 10 != 1 && x % 10 != 0) {
                    flag = 1;
                    break;
                }
                x /= 10;
            }
            if (!flag) {
                if (i % n == 0) {
                    cout << i << '\n';
                    break;
                }
            }
        }
    }
    return 0;
}


思路:每次将前一个数*10和*10+1放入队列中,bfs搜索

#include
#include
using namespace std;
typedef long long ll;
int n;
void bfs(int n) {
    queueq;
    q.push(1);
    while (!q.empty()) {
        if (q.front() % n == 0) {
            cout << q.front() << '\n';
            break;
        }
        ll now=q.front();
        q.pop();
        q.push(now * 10);
        q.push(now * 10 + 1);
    }
}
int main()
{
    ios::sync_with_stdio(false);
    while (cin >> n &&n) {
        bfs(n);
    }
    return 0;
}


D - Shuffle'm Up
思路:dfs,利用string可加性按要求分成两部分之后合为一部分,当未遇见目标清空原有再次按要求分两部分,当遇见目标返回次数,
 关键在于当得不到目标时输出-1,因为拆分再按要求合为一部分的不同个数有限,于是可以利用set只包含不同的个数
当重复出现时return,并且所用不同个数得不到目标并且重复出现可以得出得不到目标;

#include 
#include 
#include 
#include 
using namespace std;
set  Set;
string s, s3;
int ans,m;
void dfs(string s1, string s2, int n) {
    s3.clear();
    for (int i = 0; i < m; i++) {
        s3+=s2[i];
        s3+=s1[i];
    }
    if (Set.count(s3)) return;
    Set.insert(s3);
    if (s3 == s) {
        ans = n;
        return;
    }
    else {
        s1.clear();
        s2.clear();
        for (int i = 0; i < m; i++) {
            s1+=s3[i];
        }
        for (int i = m; i < m * 2; i++) {
            s2+=s3[i];
        }
        dfs(s1, s2, n + 1);
    }
}

int main(void) {
    string s1, s2;
    int t;
    cin >> t;
    for (int i = 1; i <= t; i++) {
        Set.clear();
        cin >> m;
        cin >> s1 >> s2 >> s;
        ans = -1;
        dfs(s1, s2, 0);
        if (ans == -1)
            cout << i << " " << ans << '\n';
        else
            cout << i << " " << ans+1 << '\n';
    }
    return 0;
}


E - PotsF - Oil Deposits
 思路:遍历每一个'#',遇见就dfs并ans++,并在将dfs中将八个方向中'#'变为'*'

#include
using namespace std;
const int maxn = 110;
char mp[maxn][maxn];
bool vis[maxn][maxn];
int ans;
int n, m;
int dir[8][2] = { {1,1},{1,-1},{-1,1},{-1,-1},{1,0},{0,1},{-1,0},{0,-1} };
bool in(int x, int y) {
    return x <= m && x >= 1 && y <= n && y >= 1;
}
void dfs(int x, int y) {
    vis[x][y] = 1;
    mp[x][y] = '*';
    for (int i = 0; i < 8; i++) {
        int tx = x + dir[i][0];
        int ty = y + dir[i][1];
        if (in(tx, ty) && !vis[tx][ty] && mp[tx][ty] == '@')
            dfs(tx, ty);
    }

}
int main()
{
    ios::sync_with_stdio(false);
    while (cin >> m >> n && m) {
        memset(vis, 0, sizeof(vis));                 //清空数据,方便下一次使用
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                cin >> mp[i][j];
            }
        }
        ans = 0;
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (mp[i][j] == '@') {
                    dfs(i, j);
                    ans++;
                }
            }
        }
        cout << ans << '\n';
    }
    return 0;
}



J - 哈密顿绕行世界问题
思路:链式前向星存图+dfs遇见起点位置并且步数满足输出+回溯
 

#include 
#include
#include
#include
using namespace std;
const int maxn = 100;
int num = 1, cnt = 1;
int vis[maxn],head[maxn],ans[maxn];
struct Edge
{
    int v,next;
}e[maxn];
void insert(int u, int v)
{
    e[num].v = v;
    e[num].next = head[u];//head[i]表示以i为起点的最后一条边的储存位置 
    head[u] = num++;
}
void dfs(int x,int m,int sum)
{
    vis[x] = 1;
    ans[sum] = x;
    for (int i = head[x]; i; i = e[i].next){
        if (e[i].v == m && sum == 19){
            cout << cnt++ << ":  ";
            for (int j = 0; j < 20; j++)
            {
                cout << ans[j] << " ";
            }
            cout << m << endl;
        }
        if (!vis[e[i].v]){
            dfs(e[i].v,m,sum+1);
        }
    }
    vis[x] = 0;
}
int main()
{
    int m, a, b, c;
    for (int i = 1; i <= 20; i++){
        cin >> a >> b >> c;
        insert(i, c);
        insert(i, b);
        insert(i, a);
    }
    while (cin >> m)
    {
        memset(vis, 0, sizeof(vis));
        dfs(m,m,0);
    }
    return 0;
}

 M - A计划
 思路:三维广度优先搜索,只需在额外判断高度是否越界,并且在时空传输机进行额外判断时间不加,高度变化采用^
 (重点)还需考虑上下皆有时间传输机的情况,若皆有,则不入队列(这种设定太恶心了)其余设定同二维

#include
#include
const int maxn = 15;
using namespace std;
int n, m, t;
char mp[2][maxn][maxn];
int vis[2][maxn][maxn];
int dir[4][2] = { {0,-1},{-1,0},{0,1},{1,0} };
int nx, ny, nz, nd;
struct node
{
    int d, x, y, z;
    node() {};
    node(int xx, int yy, int zz, int dd) {
        d = dd;
        x = xx;
        y = yy;
        z = zz;
    }
};
bool in(int x, int y, int z)
{
    return x < 2 && x >= 0 && y < n&& y >= 0 && z < m&& z >= 0;
}
int debug = -1;
bool bfs()
{
    queueq;
    bool res = false;
    q.push(node(0, 0, 0, 0));
    while (!q.empty())
    {
        node now = q.front();
        q.pop();
        vis[now.x][now.y][now.z] = 1;
        if (mp[now.x][now.y][now.z] == 'P')
        {
            if (now.d<= t)res = true;
            else res = false;
            debug = now.d;
        }
        for (int i = 0; i < 4; i++)
        {
            if (mp[now.x][now.y][now.z] == '.' || mp[now.x][now.y][now.z] == 'S')
            {
                nx = now.x;
                ny = now.y + dir[i][0];
                nz = now.z + dir[i][1];
                nd = now.d + 1;
            }
            if (mp[now.x][now.y][now.z] == '#')
            {
                nx = now.x ^ 1;;
                ny = now.y;
                nz = now.z;
                nd = now.d;
                if (mp[nx][ny][nz] == '#')
                    continue;
            }
            if (in(nx, ny, nz)&&mp[nx][ny][nz] != '*' && !vis[nx][ny][nz])
                q.push(node(nx, ny, nz, nd));
        }
    }
    return res;
}

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < n; j++)
                for (int k = 0; k < m; k++)
                    vis[i][j][k] = 0;
        cin >> n >> m>> t;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cin >> mp[0][i][j];
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cin >> mp[1][i][j];
            }
        }
        if (bfs())
            cout << "YES" << '\n';
        else
            cout << "NO" << '\n';
    }
    return 0;
}

java学习日志(1)

一:准备
1.环境配置git,navicat,jdk,idea,mysql(下载时需将调制系统默认输入法)
2.idea上java项目文件创建:项目creat new porject -->java-->jdk(已配置);文件:src(需要将其调制源文件)-->new-->packge-->new-->java class

二:正式(结合C语言网Java教程,学习顺序略有不同)
1.基本数据类型:
 byte,short,int,long,float,double,boolean,char

2.输入输出语句:
(1)输入
需要依赖Scanner类:Scanner reader = new Scanner(System.in);
reader对象调用下列方法,读取用户在命令行输入的各种基本类型数据:
nextBoolean() nextByte() nextShort() nextInt() nextLong() nextFloat() nextDouble()
(2)输出
System.out.println()换行打印;System.out.print()不换行打印;System.out.printf()按格式输出;

3.运算符和表达式
(1)算数,关系,逻辑,位,赋值,条件运算符与c大致相同
(2)多出 instanceof运算符
instanceof运算符左面的操作数是一个对象,右面的操作数是一个类,当左面的对象是右面的类或子类创建的对象时,该运算符运算的结果是true,否则是false。

4.Java流程控制
if switch for while do-while break continue return 语句与c大致相同
 
5.类与对象(大多为引入概念)
(1)类
概念:类是组成Java程序的基本要素,一个Java应用程序就是由若干个类所构成。类是Java语言中最重要的“数据类型”,类声明的变量被称作对象。
class是关键字,用来定义类
class 类名 {
    类体的内容
}
(2)Java的方法,构造方法,创建对象,使用对象,对象的引用与实体,方法重载(结合c个人理解为在结构体中创建变量,函数,然后需要声明和分配(对象的实体)之后就可使用变量和函数了)
注:在Java中,对于同一个类的两个对象object1和object2,允许进行如下的赋值操作:object1 = object2;这样object1中存放的将是object2的值
(3)Java实例变量和类变量,实例方法和类方法
class Main {
    float x; //实例变量
    static int y; //类变量
    float max(float b,float c) { //实例方法
        ……
    }
    static float max(float d,float e) { //类方法
        ……
    }
}
注:1. 不同对象的实例变量互不相同,2. 所有对象共享类变量,3. 通过类名直接访问类变量,调用类方法。
(4)this关键字
this可以出现在实例方法和构造方法中,但不可以出现在类方法中,代表使用该方法所创建的对象,通常可省去,当实例成员变量的名字和局部变量的名字相同时,成员变量前面的“this.”或“类名.”就不可以省略。

(5)Java包及存储目录
java包(package):不同Java源文件中可能出现名字相同的类,如果想区分这些类,就需要使用包名。
     package 包名;
如果源程序中省略了package语句,源文件中所定义命名的类被认为是无包名的一部分,只要这些类的字节码被存放在相同的目录中,那么它们就属于同一个包,但没有包名。
    储存目录
如果一个类有包名,那么就不能在任意位置存放它,否则虚拟机将无法加载这样的类。
例如:  package tom.jiafei;
那么存储文件的目录结构中必须包含如下结构:…\tom\jiafei,比如:C:\1000\tom\jiafei,并且要将源文件编译得到的类的字节码文件保存在目录C:\1000\tom\jiafei中,源文件可以任意存放。
如果主类的包名是tom.jiafei,那么主类的字节码一定存放在…\tom\jiafei目录中,那么必须到tom\jiafei的上一层目录中去运行主类,假设C:\1000\tom\jiafei,运行格式如下:
C:\1000> java tom\jiafei.主类名

(6)import语句
引入类库中的类:(引入一个包中的全部类,则可以用通配符号星号(*)来代替);
引入自定义包中的类:假设import tom.jiafei.*;                             (目前为了解原理,还不会操作)
法1:
用户为了使自己的程序能使用tom.jiafei包中的类,可以在classpath中指明tom.jiafei包的位置,假设包tom.jiafei的位置是C:\1000,即包名为tom.jiafei的类的字节码存放在C:\1000\tom\jiafei目录中。用户可以更新classpath的值,例如:
set classpath=C:\jdk1.6\jre\lib\rt.jar;.;C:\1000
/*表示可以加载C:\1000目录中的无名包类且C:\1000目录下的子孙目录可以作为包的名字来使用*/
法2:
如果用户不想更新classpath的值,那么用户可以在用户程序所在目录下建立和包相对应的子目录结构。
例如:用户程序中某个类所在目录是C:\2000,该类想使用import语句引入tom.jiafei包中的类,那么根据包名建立目录结构C:\2000\tom\jiafei,就不用去修改classpath的值,因为默认的classpath的值为:C:\jdk1.6\jre\lib\rt.jar;.;
/*“.;”表示可以加载应用程序当前目录中的无名包类且当前目录下的子孙目录可以作为包的名字来使用*/
(7)Java的访问权限
private 一个类中用另外一个类创建了一个对象后,该对象不能访问自己的私有变量,调用类中的私有方法。
public ....可共用
protect   一个类中用另外一个类创建了一个对象后,如果两个类在同一个包中,那么该对象能访问自己的protected变量,调用类中的protected方法。.
(8)Java基本类型封装:Byte、Integer、Short、Long、Float、Double和Character类。

6.Java的子类与继承


5.java数组
(1)声明数组(二维为例)
两种格式   类型 数组名[][]; 类型 [][] 数组名;其中 类型 [] a,b[]等价于 类型 a[],b[][];
注(Java不允许在声明数组中的方括号内指定数组元素的个数)
(2)为数组分配元素
格式   数组名 = new 数组元素的类型[数组元素的个数];
声明数组和创建数组可以一起完成   如类型 a[]=new 类型[数组元素的个数]
注 Java允许使用int型变量的值指定数组的元素的个数
(3)数组的使用(一维为例,二维,多维类似)
静态初始化:数组类型 [] 名称 = new 类型{元素},简化   数组类型 [] 名称 ={元素}
动态初始化:先声明,在后面的语句中再逐个赋值。
调用:与c类似
(4)不规则数组
静态初始化:例int Array[][] = {{1,2},{3},{4,5,6},{7,8}};
动态初始化:它不可以直接使用new int[4][3]语句,我们要先初始化高维数组,之后再分别初始化低维数组,例如
int Array[][] = new int[4][]; //先初始化高维数组为4
Array[0] = new int[2]; //逐一初始化低维数组
Array[1] = new int[1];
Array[2] = new int[3];
Array[3] = new int[2];
(5)Arrays类

你可能感兴趣的:(学习,算法,c++)