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