week4(补)

A - Bmail Computer Network

Bmail Computer Network

记录父节点,从n开始记录路径,倒着输出。

#include <iostream>
#include <stack>

using namespace std;

const int N = 200005;
int p[N];

int main()
{
    int n;
    stack<int> path;
    cin >> n;
    for(int i = 2; i <= n; i++)
    {
        cin >> p[i];
    }
    cout << 1;
    while(n != 1)
    {
        path.push(n);
        n = p[n];
    }
    while(!path.empty())
    {
        cout << " " << path.top();
        path.pop();
    }
    return 0;
}

B - Protect Sheep

Protect Sheep

直接在每个羊的周围都放上狗

#include <iostream>
#include <stack>
#include <vector>

using namespace std;

struct Animal
{
    int x;
    int y;
};

char m[503][503];
int dic[4][2] = {{0,1}, {0,-1}, {1,0}, {-1,0}};

int main()
{
    vector<Animal> sheep; // 每只羊的坐标
    int r, c, cnt = 0, flag = 0;
    cin >> r >> c;
    for(int i = 1; i <= r; i++)
    {
        for(int j = 1; j <= c; j++)
        {
            scanf("%c", &m[i][j]);
            if(m[i][j] == '\n')
            {
            	j--; // j--和j++抵消了,下次重新输入到这个地方
            }
            else if(m[i][j] == 'S')
            {
            	sheep.push_back({i,j});
            }
            else if(m[i][j] == 'W')
            {
                cnt++; // 狼的计数
            }
        }
    }
    if(cnt != 0) // 有狼,则有必要放狗
    {
        int ns = sheep.size(); // 遍历羊的坐标
        for(int i = 0; i < ns; i++)
        {
            for(int j = 0; j < 4; j++) // 四个方向能放狗就都放上
            {
                int x = sheep[i].x + dic[j][0], y = sheep[i].y + dic[j][1];
                if(m[x][y] == 'W') // 如果临近的就是狼,那就没法儿了,标记置1
                {
                	flag = 1;
                }
                else if(m[x][y] == '.')
                {
                	m[x][y] = 'D';
                }
            }
            if(flag == 1)
            {
            	break;
            }
        }
        if(flag == 1) // 不能通过放狗把狼和羊隔开
        {
            printf("No\n");
        }
    }
    if(flag == 0) // 如果没有狼,或者可以通过放狗把狼和羊隔开
    {
        printf("Yes\n");
        for(int i = 1; i <= r; i++)
        {
            for(int j = 1; j <= c; j++)
            {
                printf("%c", m[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}

C - King Escape

King Escape

以皇后为原点的直角坐标系,如果国王的位置和目标位置在一个象限内,则YES,否则NO

#include <iostream>
using namespace std;

int main()
{
    int n, ax, ay, bx, by, cx, cy, flag = 0;
    cin >> n >> ax >> ay >> bx >> by >> cx >> cy;
    // 四个象限
    if(bx < ax && by < ay && cx < ax && cy < ay)
    {
    	flag = 1;
    }
    if(bx > ax &&b y < ay && cx > ax && cy < ay)
    {
    	flag = 1;
    }
    if(bx < ax && by > ay && cx < ax && cy > ay)
    {
    	flag = 1;
    }
    if(bx > ax && by > ay && cx > ax && cy > ay)
    {
    	flag = 1;
    }
    
    if(flag)
    {
    	cout << "YES" << endl;
    }
    else
    {
    	cout << "NO" << endl;
    }
    return 0;
}

D - Rook, Bishop and King

Rook, Bishop and King


#include <iostream>

using namespace std;

int r1, r2, c1, c2;

int max(int a, int b)
{
    return a > b?a:b;
}
// rook 在同一行或者同一列的话只需要一步,否则两步
int rook()
{
    if(r1 == r2 || c1 == c2)
    {
    	return 1;
    }
    return 2;
}
// bishop 同一对角线上走一步
// abs(abs(c1-c2) - abs(r1-r2)) % 2 == 1 则无法到达,画图可知
// 否则两步
int bishop()
{
    if(r1 + c1 == r2 + c2 || r1 - c1 == r2 - c2)
    {
    	return 1;
    }
    if(abs(abs(c1-c2) - abs(r1-r2)) % 2 == 1)
    {
    	return 0;
    }
    return 2;
}
//先斜着走,再横着或竖着走,其实就是纵坐标之差和横坐标之差中大的那个
int king()
{
    return max(abs(r1-r2), abs(c1-c2));
}
int main()
{
    cin >> r1 >> c1 >> r2 >> c2;
    cout << rook() << " " << bishop() << " " << king() << endl;
    return 0;
}

E - Jumping on Walls

Jumping on Walls

深搜,需要标记数组。

#include <iostream>

using namespace std;

int n, k, flag = 0;
string sl, sr;
bool f[2][110000];
/**
 * 深搜
 * 参数 lr 左还是右,0左,1右
 * 参数 h 目前的高度
 * 参数 hw 目前水的高度
 */
void dfs(int lr, int h, int hw)
{
    if(h > n) flag = 1; // 可以出去
    // 读取string里的字符,所以h-1
    if(flag == 1 || f[lr%2][h-1] || hw >= h || h <= 0)
    {
    	return;
    }
    if(lr%2 == 0 && sl[h-1] == 'X')
    {
    	return;
    }
    if(lr%2 == 1 && sr[h-1] == 'X')
    {
    	return;
    }
    hw++;
    f[lr%2][h-1] = 1;
    dfs(lr, h-1, hw); // 下
    dfs(lr+1, h+k, hw); // 另一边
    dfs(lr, h+1, hw); // 上
    // 不知道为什么,顺序改成这个就不对了
    //  dfs(lr, h-1, hw);
    // dfs(lr, h+1, hw);
    // dfs(lr+1, h+k, hw);
}
int main()
{
    cin >> n >> k >> sl >> sr;
    dfs(0, 1, 0);
    if(flag)
    {
    	cout << "YES" << endl;
    }
    else
    {
    	cout << "NO" << endl;
    }
    return 0;
}

F - Minimal Height Tree

Minimal Height Tree

题解

除了1所在的根节点以外,每一层的连续递增子序列的个数为
上一层的结点个数时,高度最小。

#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;

int t, n;
int main()
{
    cin >> t;
    while (t--)
    {
        int ans = 0, cnt = 1, cnt2 = 0, cnt3 = 0, p, a;
        cin >> n >> p;
        for (int i = 1; i < n; i++)
        {
            cin >> a;
            if (a > p)
            {
                cnt2++; // 求连续递增的数的个数
            }
            else
            {
                cnt3++; // 求目前一层有几个连续递增的子序列
                if (cnt == cnt3) // 如果连续递增子序列个数等于上一层的节点个数
                {
                    // 当前结点为下一层的第一个节点
                    ans++; // 层数加1
                    cnt = cnt2 + cnt3 - 1; // 上一层的结点数更新为这一层
                    cnt2 = 1;
                    cnt3 = 0;
                }
            }
            p = a;
        }
        cout << (++ans) << endl;
    }
    return 0;
}

Catch That Cow

Catch That Cow

广搜

#include <iostream>
#include <queue>

using namespace std;

typedef long long ll;

struct node
{
    ll x;
    ll cnt;
};

bool vis[100005] = {};

int main()
{
    ll ans = 0, n, k;
    queue<node> que;

    cin >> n >> k;

    node t = {n, 0};
    que.push(t);
    while (!que.empty())
    {
        node a = que.front();
        que.pop();
        if (a.x == k)
        {
            ans = a.cnt;
            break;
        }
        else
        {
            a.cnt++;
            ll b[3] = {a.x - 1, a.x + 1, 2 * a.x};
            for (int i = 0; i < 3; i++)
            {
                if (b[i] < 0 || b[i] > 100000 || vis[b[i]])
                {
                    continue;
                }
                vis[b[i]] = 1;
                a.x = b[i];
                que.push(a);
            }
        }
    }
    cout << ans << endl;
    return 0;
}

H - Asteroids

Asteroids

匈牙利算法

#include <iostream>
#include <cstring>

using namespace std;

int n, k, x, y, cnt = 0;
bool m[505][505] = {};
bool vis[505] = {};
int p[505] = {};

bool match(int x)
{
    for (int i = 1; i <= n; i++)
    {
        if (m[x][i] == 1 && !vis[i])
        {
            vis[i] = true;
            if (p[i] == 0 || match(p[i]))
            {
                p[i] = x;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    cin >> n >> k;

    for (int i = 0; i < k; i++)
    {
        cin >> x >> y;
        m[x][y] = 1;
    }
    for (int i = 1; i <= n; i++)
    {
        memset(vis, 0, sizeof(vis));
        if (match(i))
        {
            cnt++;
        }
    }
    cout << cnt << endl;
    return 0;
}

I - Antenna Placement

Antenna Placement

拆点,最小点覆盖,匈牙利算法

#include <iostream>
#include <cstring>

using namespace std;

bool vis[500], bgraph[500][500];
int Map[42][12];
int h, w, cntv, p[500];

int match(int x)
{
    for (int i = 1; i <= cntv; i++)
    {
        if (vis[i] == 0 && bgraph[x][i])
        {
            vis[i] = 1;
            if (p[i] == 0 || match(p[i]))
            {
                p[i] = x;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        memset(bgraph, 0, sizeof(bgraph));
        memset(Map, 0, sizeof(Map));
        memset(p, 0, sizeof(p));

        cin >> h >> w;

        getchar();
        cntv = 0;
        for (int i = 1; i <= h; i++)
        {
            for (int j = 1; j <= w; j++)
            {
                Map[i][j] = (int)(getchar());
                if (Map[i][j] == '*')
                {
                    Map[i][j] = (++cntv);
                    if (Map[i-1][j])
                    {
                        bgraph[cntv][Map[i-1][j]] = 1;
                        bgraph[Map[i-1][j]][cntv] = 1;
                    }
                    if (Map[i][j - 1])
                    {
                        bgraph[cntv][Map[i][j-1]] = 1;
                        bgraph[Map[i][j-1]][cntv] = 1;
                    }
                }
                else
                {
                    Map[i][j] = 0;
                }
            }
            getchar();
        }

        int ans = 0;
        for (int i = 1; i <= cntv; i++)
        {
            memset(vis, 0, sizeof(vis));
            if (match(i))
            {
                ans++;
            }
        }
        cout << cntv - ans / 2 << endl;
    }
    return 0;
}

J - Sorting It All Out

Sorting It All Out

拓扑排序

#include <iostream>
#include <queue>
#include <cstring>

using namespace std;

int n, m, ans[30];
char a, b;

int topo(vector<int> *Map, int *num)
{
    queue<int> q;
    int c = 0, flag = 0, in[26];
    for (int i = 0; i < 26; i++)
    {
        in[i] = num[i]; // 复制一份入度的统计数组以供拓扑排序
    }
    for (int j = 0; j < 26; j++)
    {
        if (Map[j].size() != 0 && num[j] == 0)
        {
            q.push(j);
        }
    }
    while (!q.empty())
    {
        if (q.size() > 1)
        {
            flag = 1; // 多于一个点,则这几个点还排不出来,不能直接 break,因为还要判断有没有环
        }

        int x = q.front();
        q.pop();

        if (!flag)
        {
            ans[c++] = x; // 顺利的话把排好的存到数组里
        }

        for (size_t i = 0; i < Map[x].size(); i++) // 将x点和它的边隐藏
        {
            int t = Map[x][i];
            in[t]--; // 依次减少入度
            if (in[t] == 0)
            {
                q.push(t); // 入度为0则进入队列
            }
        }
    }
    for (int i = 0; i < 26; i++)
    {
        if (in[i])
        {
            return -1; // 存在环
        }
    }
    if (flag || c < n)
    {
        return 0; // 未排好序
    }
    return 1; // 排好序了
}

int main()
{
    while (scanf("%d%d", &n, &m) != EOF && n && m)
    {
        // num记录入度,cnt记录在哪里就已经排好序或者出现环,f接收拓扑排序结果
        int num[26] = {}, cnt = 0, f = 0;
        vector<int> Map[26];

        getchar(); // 吞掉回车
        for (int i = 1; i <= m; i++)
        {
            scanf("%c<%c", &a, &b);
            if (!f) // 还没排好或者还未发现环则继续排
            {
                Map[a - 'A'].push_back(b - 'A');
                num[b - 'A']++;
                f = topo(Map, num);
                cnt = i;
            }
            getchar(); // 吞掉回车
        }
        if (f == 1)
        {
            cout << "Sorted sequence determined after " << cnt << " relations: ";
            for (int i = 0; i < n; i++)
            {
                cout << (char)(ans[i] + 'A');
            }
            cout << "." << endl;
        }
        else if (!f)
        {
            cout << "Sorted sequence cannot be determined." << endl;
        }
        else
        {
            cout << "Inconsistency found after " << cnt << " relations." << endl;
        }
    }
    return 0;
}

K - Trees Made to Order

Trees Made to Order

写的太冗长了,不想多说

#include <iostream>
#include <vector>

using namespace std;

int a[20] = {1}, b[20] = {1};
int Map1[20][20], Map2[20][20];
vector<int> vc[20];

struct Node
{
    int x;
    Node *l;
    Node *r;
    Node(int a): x(a)
    {
        l = NULL;
        r = NULL;
    }
};

void create(int i, int j, Node *p, int l, int r)
{
    if (i <= 1)
    {
        return;
    }
    if (j != 0)
    {
        p->l = new Node(j);
        if (j > 1)
        {
            int k, m;
            for (k = 0; k < j && l >= Map2[j][k]; k++);

            if (k == 0)
            {
                m = l;
            }
            else
            {
                m = l - Map2[j][k - 1];
            }

            create(j, k, p->l, m / a[j - k - 1], m % a[j - k - 1]);
        }
    }
    j = i - j - 1;
    if (j != 0)
    {
        p->r = new Node(j);
        if (j > 1)
        {
            int k, m;
            for (k = 0; k < j && r >= Map2[j][k]; k++);

            if (k == 0)
            {
                m = r;
            }
            else
            {
                m = r - Map2[j][k - 1];
            }

            create(j, k, p->r, m / a[j - k - 1], m % a[j - k - 1]);
        }
    }

}
void Order(Node *T)
{
    if (T == NULL)
    {
        return;
    }

    printf("(");
    if (T->l != NULL)
    {
        Order(T->l);
    }
    printf("X");
    if (T->r != NULL)
    {
        Order(T->r);
    }
    printf(")");

}
void release(Node *T)
{
    if (T->l)
    {
        release(T->l);
    }
    if (T->r)
    {
        release(T->r);
    }
    delete T;
}

int main()
{
    int n;
    for (int i = 1; i < 19; i++)
    {
        for (int j = 0; j < i; j++)
        {
            Map1[i][j] = a[j] * a[i - j - 1]; //Map1[i][j]表示i个结点的二叉树左子树结点数位j时有多少种
            Map2[i][i] += Map1[i][j];
            Map2[i][j] = Map2[i][i];
        }
        a[i] += Map2[i][i]; //a[i],结点数为i的树的个数
        b[i] = a[i] + b[i - 1];
    }

    while (scanf("%d", &n) != EOF && n)
    {
        Node *Tree = new Node(n);

        int i = 0, j = 0, l = 0, r = 0, nextl = 0;

        for (; i < 20 && n >= b[i]; i++);
        nextl  = n - b[i - 1]; //i为结点个数,在i个结点的树里排第nextl个,nextl范围[0,a[i]-1]

        for (j = 0; j < i && nextl >= Map2[i][j]; j++);

        //j为左子树结点个数,i-j-1是右子树结点个数
        if (j == 0)
        {
            r = nextl;
        }
        else
        {
            r = nextl - Map2[i][j - 1];
        }

        l = r / a[i - j - 1];
        r = r % a[i - j - 1];
        create(i, j, Tree, l, r);

        Order(Tree->l);
        printf("X");
        Order(Tree->r);
        printf("\n");

        release(Tree);
    }
    return 0;
}

L - Agri-Net

Agri-Net

Kruskal

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;

struct Node
{
    int x;
    int y;
    int w;
    
	bool operator< (Node b)
	{
	    return w < b.w;
	}
} edge[10000];

int p[105];

int Find(int x)
{
    if (x != p[x])
    {
        p[x] = Find(p[x]);
    }
    return p[x];
}

int main()
{
    int n;
    while (cin >> n)
    {
        int cnt = 0, i = 0, j = 0, t;
        for (i = 1; i <= n; i++)
        {
            p[i] = i;
        }
        for (i = 1; i <= n; i++)
        {
            for (j = 1; j <= n; j++)
            {
                cin >> t;
                if (i < j)
                {
                    edge[++cnt].w = t;
                    edge[cnt].x = i;
                    edge[cnt].y = j;
                }
            }
        }
        sort(edge + 1, edge + cnt + 1, cmp);
        ll ans = 0;
        for (i = 1, j = 1; i < n && j <= cnt; j++)
        {
            int a = Find(edge[j].x), b = Find(edge[j].y);
            if (a != b)
            {
                ans += edge[j].w;
                p[a] = b;
                i++;
            }
        }
        cout << ans << endl;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
综合小区管理系统管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、车位管理、车位分配管理、出入管理、字典管理、房屋管理、物业费缴纳管理、公告管理、物业人员投诉管理、我的私信管理、物业人员管理、用户管理、管理员管理。用户的功能包括管理部门以及部门岗位信息,管理招聘信息,培训信息,薪资信息等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 综合小区管理系统管理系统可以提高综合小区管理系统信息管理问题的解决效率,优化综合小区管理系统信息处理流程,保证综合小区管理系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理综合小区管理系统信息,包括出入管理,报修管理,报修管理,物业费缴纳等,可以管理操作员。 出入管理界面,管理员在出入管理界面中可以对界面中显示,可以对招聘信息的招聘状态进行查看,可以添加新的招聘信息等。报修管理界面,管理员在报修管理界面中查看奖罚种类信息,奖罚描述信息,新增奖惩信息等。车位管理界面,管理员在车位管理界面中新增。公告管理界面,管理员在公告管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值