• 爬格子呀--一堆东西


    好久没上传了,主要是因为期中考试的复习,没有足够的时间来写
    期中考试大物不及格,但是数学建模校赛却拿到了二等奖,塞翁失马吧
    好几道题这次是,发现越来越难了,但却好像又有规律可循
    代码如下:

    Uva1343旋转游戏

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int a[24];
    char ans[10000];
    //表格的线性化
    /*
          00    01
          02    03
    04 05 06 07 08 09 10
          11    12
    13 14 15 16 17 18 19
          20    21
          22    23
    */
    
    int mat[8][7] = {
        { 0,2,6,11,15,20,22 },//A 0
        { 1,3,8,12,17,21,23 },//B 1
        { 10,9,8,7,6,5,4 },//C 2
        { 19,18,17,16,15,14,13 },//D 3 
        { 23,21,17,12,8,3,1 },//E 4
        { 22,20,15,11,6,2,0 },//F 5
        { 13,14,15,16,17,18,19 },//G 6
        { 4,5,6,7,8,9,10 },//H 7
    };
    
    int center[8] = { 6,7,8,11,12,15,16,17 };
    
    //判断是否达到最终情况
    bool tar() {
        for (int i = 0; i < 8; i++) 
            if (a[center[i]] != a[center[0]])
                return false;
        return true;
    }
    //寻找1、2、3三个数在中圈中的数值与目标不一样的个数,数量越小,表示1、2、3在中圈中的个数越多
    int time(int k) {
        int ans = 0;
        for (int i = 0; i < 8; i++) {
            if (a[center[i]] != k)
                ans++;
        }
        return ans;
    }
    
    //寻找最小值
    int find_min() {
        return min(min(time(1), time(2)), time(3));
    }
    
    //移动棋盘序列
    void move(int i) {
        int mid = a[mat[i][0]];
        int j = 0;
        for (; j < 6; j++) {
            a[mat[i][j]] = a[mat[i][j + 1]];
        }
        a[mat[i][6]] = mid;
    }
    
    //dfs建立在递归的基础上
    //这个dfs用到了IDA*的算法进行剪枝,d为深度,maxd为目标上限find_min为乐观估价函数,与深度相加判断是否越界
    bool dfs(int d, int maxd) {
        //与dfs类似,优先判断是否满足条件
        if (tar()) {
            for (int i = 0; i < d; i++) {
                putchar(ans[i]);
            }
            //ans[d] = '';
            //printf("%s
    ", ans);
            return true;
        }
        //IDA*的判断
        if (d + find_min() > maxd)
            return false;
        int t[24];
    //  memcpy(t, a, sizeof(a));
        for (int i = 0; i < 8; i++) {
            ans[d] = 'A' + i;
            //这一步的ans[d]很关键,因为d只有在这一次迭代成功的时候才会改变
            //这就保证了可以通过循环来深度遍历,并且不断的更新
            move(i);
            if (dfs(d + 1,maxd))
                return true;
            //若失败,则清除上面的移动
            //memcpy(a, t, sizeof(a));
            int mid = (i + 4) % 8;
            mid % 2 == 0 ? move(mid + 1) : move(mid - 1);
        }
        return false;
    }
    
    int main() {
        while (scanf("%d",&a[0]), a[0]!=0) {
            for (int i = 1; i < 24; i++)
                scanf("%d", &a[i]);
            if (tar())
                printf("No moves needed");
            else
                for (int maxd = 1; ; maxd++)
                    if (dfs(0,maxd));
                        break;
            printf("%d", a[center[0]]);
        }
        return 0;
    }

    Uva818–切断圆环链

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<deque>
    #include<utility>
    using namespace std;
    typedef pair<int, int> p;
    const int maxn = 15;
    int node, n, t;
    deque<p>store[maxn + 1];
    
    bool can_find(int i, p pp) {
        for (deque<p>::iterator it=store[i].begin();it!=store[i].end(); advance(it,1))
            if ((*it).first == pp.first) {
                if (it == store[i].begin()) {
                    store[i].push_front(make_pair(pp.second, pp.first));
                    return true;
                }
                node++;
                store[++t].push_back(pp);
                return true;
            }
        return false;
    }
    
    int main() {
        p pp;
        scanf("%d", &n);
        scanf("%d %d", &pp.first, &pp.second);
        store[t].push_back(pp);
        while (n != 0) {
            scanf("%d %d", &pp.first, &pp.second);
            if (pp.first == -1 && pp.second == -1)
                break;
            for (int i = 0; i <= t; i++) {
                int size = store[i].size();
                if (size == 0) {
                    store[i].push_back(pp);
                    break;
                }
                //判断能否插入到末尾
                if (store[i][size - 1].second == pp.first)
                {
                    store[i].push_back(pp);
                    //判断是否为大环
                    if (store[i][0].first == pp.second) {
                        node++;
                        t++;
                        break;
                    }
                    break;
                }
                //判断是否为一环套多环
                else if (can_find(i, pp))
                    break;
            }
        }
        printf("%d", node);
        return 0;
    }

    Uva1602–网格动物

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<set>
    using namespace std;
    const int maxn = 10;
    int n, w, h;
    int dir[4][2] = { { 0,1 },{ 0,-1 },{ 1,0 },{ -1,0 } };
    
    struct cell {
        int x, y;
        cell(int x = 0, int y = 0) :x(x), y(y) {};//函数包含默认构涵,可以显示的构造自己想要的特定结构体
        bool operator < (const cell &rhs)const {
            return x < rhs.x || (x == rhs.x && y < rhs.y);
        }
    };
    
    #define FOR_CELL(c,p) for(set<cell>::const_iterator c=(p).begin();c!=(p).end();c++)
    //规范化,根据书上面讲的,应该是想通过做差值来减少运算量???
    inline set<cell> normalize(const set<cell>&p) {
        int minx = p.begin()->x, miny = p.begin()->y;
        FOR_CELL(c, p) {
            minx = min(minx, c->x);
            miny = min(miny, c->y);
        }
        set<cell>pp;
        FOR_CELL(c, p) {
            pp.insert(cell(c->x - minx, c->y - miny));
        }
        return pp;
    }
    //旋转,坐标运算
    inline set<cell> rotate(const set<cell>&p) {
        set<cell>pp;
        FOR_CELL(c, p) {
            pp.insert(cell(c->y, -c->x));
        }
        return normalize(pp);
    }
    //对称,坐标运算
    inline set<cell> flip(const set<cell>&p) {
        set<cell>pp;
        FOR_CELL(c, p) {
            pp.insert(cell(c->x, -c->y));
        }
        return normalize(pp);
    }
    
    set<set<cell>>poly[maxn + 1];
    int ans[maxn + 1][maxn + 1][maxn + 1];//三维数组,表示三个限定条件下的结果,这个是提前计算的需要
    
    //检查,如果点new_cell无法通过p中已有的点的坐标变化得到,就说明p是一个新的点,将其加入到点集中
    void check(const set<cell>& p, const cell &new_cell) {
        set<cell>pp = p;
        pp.insert(new_cell);
        pp = normalize(pp);
        int n = pp.size();
        for (int i = 0; i < 4; i++) {
            if (poly[n].count(pp) != 0)
                return;
            pp = rotate(pp);
        }
        pp = flip(pp);
        for (int j = 0; j < 4; j++) {
            if (poly[n].count(pp) != 0)
                return;
            pp = rotate(pp);
        }
        poly[n].insert(pp);
    }
    //计算函数
    void generate() {
        set<cell>s;
        s.insert(cell(0, 0));
        poly[1].insert(s);
        //网格多边形从1开始
        for (int n = 2; n <= maxn; n++) {
            for (set<set<cell>>::iterator p = poly[n - 1].begin(); p != poly[n - 1].end(); p++) {
                FOR_CELL(c, *p)
                    for (int i = 0; i < 4; i++) {
                        cell new_cell(c->x + dir[i][0], c->y + dir[i][1]);
                        if (p->count(new_cell) == 0)
                            check(*p, new_cell);
                    }
            }
        }
        //提前计算,逆回归过程
        for (int n = 1; n <= maxn; n++)
            for (int w = 1; w <= maxn; w++)
                for (int h = 1; h <= maxn; h++) {
                    int num = 0;
                    for (set<set<cell>>::iterator p = poly[n].begin(); p != poly[n].end(); p++) {
                        int maxx = 0, maxy = 0;
                        FOR_CELL(c, *p) {
                            maxx = max(maxx, c->x);
                            maxy = max(maxy, c->y);
                        }
                        if (min(maxx, maxy) < min(w, h) && max(maxx, maxy) < max(w, h))
                            num++;
                    }
                    ans[n][w][h] = num;
                }
    }
    
    int main() {
        generate();
        while (scanf_s("%d%d%d", &n, &w, &h) == 3) {
            printf("%d
    ", ans[n][w][h]);
        }
        return 0;
    }
    

    Uva11214–守卫棋盘(八皇后改版)

    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<memory.h>
    using namespace std;
    int map[15][15], vis[4][15];
    int kase, maxn, m, n;
    
    bool check() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (map[i][j] && !vis[0][i] && !vis[1][j] && !vis[2][i + j] && !vis[3][n - i + j])
                    return false;
            }
        }
        return true;
    }
    
    bool dfs(int cur,int d,int ma_xn) {
        if (d == ma_xn) {
            if (check()) {
                printf("Case %d: %d
    ", ++kase, d);
                return true;
            }
            return false;
        }
        for (int i = cur; i < n*m; i++) {
            int x = i / m, y = i%m;
            int midx = vis[0][x], midy = vis[1][y], mid_d1 = vis[2][x + y], mid_d2 = vis[3][n - x + y];
            vis[0][x] = vis[1][y] = vis[2][x + y] = vis[3][n - x + y] = 1;
            if (dfs(i, d + 1, ma_xn))
                return true;
            vis[0][x] = midx, vis[1][y] = midy, vis[2][x + y] = mid_d1, vis[3][n - x + y] = mid_d2;
        }
        return false;
    }
    
    int main() {
        while (scanf("%d", &n) && n) {
            scanf("%d", &m);
            char s[15];
            memset(map, 0, sizeof(map));
            for (int i = 0; i < n; i++) {
                scanf("%s", s);
                for (int j = 0; j < m; j++) {
                    if (s[j] == 'X')
                        map[i][j] = 1;
                }
            }
            for(maxn=0;;maxn++){
                memset(vis, 0, sizeof(vis));
                if (dfs(0, 0, maxn))
                    break;
            }
        }
        return 0;
    }
    

    Uva817–数字表达式

    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<stack>
    #include<deque>
    using namespace std;
    char symbol[4] = { '*','+','-',' ' };
    char num[20], sign[20];
    int kase, amount, len;
    int num2[20];
    deque<int>tar, ans;
    
    bool ok() {
        //tar储存数字,notation储存符号;
        int len2 = strlen(sign);
        int mid, i, j;
        for (i = len2 - 1, mid = 0; i >= 0; i--) {
            if (!isdigit(sign[i])) {
                mid = 0;
                tar.push_front(mid);
                continue;
            }
            mid = mid * 10 + num[i] - '0';
        }
        deque<int>::iterator it = tar.begin();
        for (i = 0; i < strlen(sign); i++) {
            if (!isdigit(sign[i])) {
                if (sign[i] == '*') {
                    tar[i] *= tar[i + 1];
                    advance(it, i + 1);
                    tar.erase(it);
                    it = tar.begin();
                }
                else if (sign[i] == '+') {
                    tar[i] += tar[i + 1];
                    advance(it, i + 1);
                    tar.erase(it);
                    it = tar.begin();
                }
                else {
                    tar[i] -= tar[i + 1];
                    advance(it, i + 1);
                    tar.erase(it);
                    it = tar.begin();
                }
            }
            else
                continue;
        }
        if (tar[0] == 2000) {
            for (i = 0; i < tar.size()-1; i++) {
                char *pp = (char*)&tar[i];
                ans.push_back(*pp);
                ans.push_back(sign[i]);
            }
            char *pp = (char*)&tar[i];
            ans.push_back(*pp);
            return true;
        }
        else
            return false;
    }
    
    void dfs(int d) {
        if (d + 2 == len) {
            if (ok())
                printf("  %s=
    ", ans), amount++;
            return;
        }
        for (int i = 0; i < 4; i++) {
            sign[d] = symbol[i];
            dfs(d + 1);
        }
    }
    
    int main() {
        while (scanf("%s", num) == 1 && num[0] != '=') {
            memset(sign, '0', sizeof(sign));
            amount = 0;
            len = strlen(num);
            for (int i = 0; i < len - 2; i++)
                num2[i] = num[i] - '0';
            dfs(0);
            printf("Problem %d", ++kase);
            if (!amount)
                printf("IMPOSSIBLE");
        }
        return 0;
    }

    Uva12107–数字谜

    //copy from liudongbohehe
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    char s[3][6];
    int len[3], maxd;
    char change[12] = "*0123456789";
    
    bool check_result() {
        char check_str[12];
        char ss[12];
        int t0 = 0, t1 = 0, t2;
        for (int i = 0; i < len[0]; i++)
            t0 = t0 * 10 + s[0][i] - '0';
        for (int i = 0; i < len[1]; i++)
            t1 = t1 * 10 + s[1][i] - '0';
        t2 = t0*t1;
        //上面计算出t2之后,这一步是用t2对check_str[]进行一个逆向的填充
        for (int i = 0; i < len[2]; i++) {
            check_str[len[2] - i - 1] = t2 % 10 + '0';//先填充高位的方法
            t2 /= 10;
        }
        //检查是否t2被除尽以及首字符是否为0
        if (t2 != 0 || check_str[0] == '0')
            return 0;
        for (int i = 0; i < len[2]; i++) 
            if (check_str[i] != s[2][i] && s[2][i] != '*')
                return 0;
        return 1;
    }
    
    //这个检查其实也是一个dfs
    int check(int a, int b) {
        int flag = 0;
        if (a == 2)
            return check_result();
        int ta, tb;
        char ch = s[a][b];
        if (len[a] - 1 == b) {
            ta = a + 1;
            tb = 0;
        }
        else {
            ta = a;
            tb = b + 1;
        }
        if (s[a][b] == '*') {
            for (int i = 1; i < 11; i++) {
                if (b == 0 && i == 1)
                    continue;
                s[a][b] = change[i];
                flag += check(ta, tb);
                if (flag > 1)
                    break;
            }
        }
        else flag += check(ta, tb);
        s[a][b] = ch;
        return flag;
    }
    
    //dfs+IDA*
    bool dfs(int a, int b, int d, int max_d) {
        int flag = 0;
        //如果深度等于阈值,则进行判断
        if (d == max_d) {
            if (check(0, 0)==1)
                return true;
            else
                return false;
        }
        if (a == 3)
            return false;
        int ta, tb;
        //tmp保存数值,dfs每次迭代的对象是目标数组中的每个元素
        char tmp = s[a][b];
        if (b == len[a] - 1) {
            ta = a + 1;
            tb = 0;
        }
        else {
            ta = a;
            tb = b + 1;
        }
        //依次枚举
        for (int i = 0; i < 11; i++) {
            if (b == 0 && i == 1)
                continue;
            if (tmp == change[i]) {//判断是否需要替换数字
                s[a][b] = tmp;
                flag = dfs(ta, tb, d, max_d);//没有换数字所以没有进行深度的叠加
            }
            else {
                s[a][b] = change[i];
                flag = dfs(ta, tb, d + 1, max_d);
            }
            if (flag)
                break;
        }
        if (!flag)//没有找到,迭代失败,归还原值
            s[a][b] = tmp;
        return flag;
    }
    
    int main() {
        int kase=0;
        memset(s, '0', sizeof(s));
        while (1) {
            scanf("%s", s[0]);
            if (s[0][0] == '0')
                break;
            scanf(" %s %s", s[1], s[2]);
            for (int i = 0; i < 3; i++)
                len[i] = strlen(s[i]);
            //maxd = 0;
            for (maxd = 0;; maxd++) {
                //IDA*
                if (dfs(0, 0, 0, maxd))
                    break;
            }
            printf("Case %d: %s %s %s
    ", ++kase, s[0], s[1], s[2]);
            memset(s, '', sizeof(s));
        }
        return 0;
    }

    Uva690–流水线调度

    //copy from xuli
    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<memory.h>
    #include<algorithm>
    using namespace std;
    int n, ans, ndis;
    int table[5], dis[24];
    string str;
    
    void dfs(int t[5], int d, int len) {
        if (d == 10) {
            ans = min(len, ans);
            return;
        }
        if (len + dis[0] * (10 - d) >= ans)
            return;
        for (int i = 0; i < ndis; i++) {
            int tmpdis = dis[i];
            bool flag = true;
            for (int j = 0; j < 5; j++) {
                if ((t[j] >> tmpdis)&table[j])
                    flag = false;
            }
            if (!flag)
                continue;
            int tmpt[5];
            for (int j = 0; j < 5; j++)
                tmpt[j] = (t[j] >> tmpdis) | table[j];
            dfs(tmpt, d + 1, len + tmpdis);
        }
        return;
    }
    
    int main() {
        while (scanf("%d",&n) && n) {
            memset(table, 0, sizeof(table));
            for (int i = 0; i < 5; i++) {
                cin >> str;
                for (int j = 0; j < n; j++) {
                    if (str[j] == 'X') {
                        table[i] |= (1 << j);
                    }
                }
            }
            ans = n * 10;
            ndis = 0;
            bool b;
            for (int i = 1; i <= n; i++) {
                b = true;
                for (int j = 0; j < 5; j++) {
                    if (table[j] & (table[j] >> i))
                        b = false;
                }
                if (b)
                    dis[ndis++] = i;
            }
            dfs(table, 1, n);
            printf("%d", ans);
        }
        return 0;
    }

    Uva12113–重叠的正方形

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<memory.h>
    using namespace std;
    //string ini[5], tar[5];
    char ini[10][15], tar[10][15];
    int vis[9];
    
    bool dfs(int cur) {
        bool flag = false;
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 9; j++) {
                if (ini[i][j] != tar[i][j]) {
                    flag = true;
                    break;
                }
            }
            if (flag)
                break;
        }       
        if (!flag)
            return true;
        if (cur >= 6)
            return false;
        char save[10][15];
        memcpy(save, ini, sizeof(ini));
        for (int i = 0; i < 9; i++) {
            if (!vis[i]) {
                int r = i / 3, c = (i % 3) * 2 + 1;
                ini[r][c] = ini[r][c + 2] = ini[r + 2][c] = ini[r + 2][c + 2] = '_';
                ini[r + 1][c - 1] = ini[r + 2][c - 1] = ini[r + 1][c + 3] = ini[r + 2][c + 3] = '|';
                ini[r + 1][c] = ini[r + 1][c + 1] = ini[r + 2][c + 1] = ini[r + 1][c + 2] = ' ';
                vis[i] = 1;
                if (dfs(cur + 1))
                    return true;
                memcpy(ini, save, sizeof(save));
                vis[i] = 0;
            }
        }
        return false;
    }
    
    int main() {
        int kase = 0;
        while (1) {
            memset(tar, 0, sizeof(tar));
            scanf("%c", &tar[0][0]);
            if (tar[0][0] == '0')
                break;
            for(int i=1;i<9;i++)
                scanf("%c", &tar[0][i]);
            getchar();
            getchar();
            for (int i = 1; i < 5; i++) {
                for (int j = 0; j < 9; j++) {
                    scanf("%c", &tar[i][j]);
                }
                getchar();
                getchar();
            }
            memset(ini, ' ', sizeof(ini));
            memset(vis, 0, sizeof(vis));
            printf("Case %d: ", ++kase);
            if (dfs(0))
                printf("Yes
    ");
            else
                printf("No
    ");
        }
        return 0;
    }

    继续加油~~

  • 相关阅读:
    c++string字符存取 安静点
    c++ string赋值操作 安静点
    c++ string字符串比较 安静点
    c++string子串 安静点
    c++vector容器 安静点
    c++string容器 构造函数 安静点
    c++ string查找和替换 安静点
    函数柯里化
    419测试神经网络计算过程
    linux 查看文件行号
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9489850.html
Copyright © 2020-2023  润新知