爬格子呀--一堆东西

来源:互联网 发布:电脑音乐剪辑软件 编辑:程序博客网 时间:2024/04/30 23:16

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

Uva1343旋转游戏

#include<cstdio>#include<cmath>#include<algorithm>using namespace std;int a[24];char ans[10000];//表格的线性化/*      00    01      02    0304 05 06 07 08 09 10      11    1213 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] = '\0';        //printf("%s\n", 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\n", 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\n", ++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=\n", 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;}//这个检查其实也是一个dfsint 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\n", ++kase, s[0], s[1], s[2]);        memset(s, '\0', 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\n");        else            printf("No\n");    }    return 0;}

继续加油~~