Uva 208:
题意:
输入n个结点的无向图及某个节点k,字典序升序输出n到k的所有道路,不可重复经过结点
题解:
dfs裸搜会T,所以需要每次搜索的时候都判断一下搜索的这个节点与目的节点能否联通,这里用并查集实现这个功能,若两个结点在同一集合中就表示为联通
代码如下:
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
//FILE* fp = fopen("stdout.txt", "w");
const int maxn = 20 + 5;
int g[maxn][maxn];
int ans[maxn];
int vis[maxn];
int k, tot, mx, kase;
int set[1000000];
int findSet(int x) {
if (x == set[x]) return x;
else return set[x] = findSet(set[x]);
}
void unionSet(int x, int y) {
int fx = findSet(x);
int fy = findSet(y);
if (fx != fy) {
set[fy] = fx;
}
}
void dfs(int cur,int num) {
if (cur == k) {
printf("1");
for (int i = 0; i < num-1; i++) {
printf(" %d", ans[i]);
}
printf(" %d
", ans[num - 1]);
tot++; return;
}
for (int i = 1; i <= mx; i++) {
if (g[cur][i] && !vis[i]&&findSet(i)==findSet(k)) {
ans[num] = i; vis[i] = 1;
dfs(i, num + 1);
vis[i] = 0;
}
}
return;
}
void ini() {
tot = 0;
memset(vis, 0, sizeof(vis));
for (int i = 0; i < maxn; i++)
memset(g[i], 0, sizeof(g[i]));
for (int i = 1; i <= 10000; i++) {
set[i] = i;
}
return;
}
int main() {
while (scanf("%d", &k)!=EOF) {
ini();
int x, y;
while (scanf("%d %d", &x, &y)) {
if (x == 0 && y == 0)break;
else { g[x][y]++; g[y][x]++; }
mx = max(mx, max(x, y));
unionSet(x, y);
}
vis[1] = 1;
printf("CASE %d:
", ++kase);
if (findSet(k) != findSet(1)) {
printf( "There are %d routes from the firestation to streetcorner %d.
", 0, k);
continue;
}
if (k == 1) {
printf( "1
There are 1 routes from the firestation to streetcorner %d.
", 1, k);
continue;
}
dfs(1,0);
printf("There are %d routes from the firestation to streetcorner %d.
", tot, k);
}
//fclose(fp);
return 0;
}
Uva225黄金图形
题意:
平面上有n个障碍点,从(0,0)出发,要求走n步回到起点,第n次需要走的距离为n。每次必须要转九十度变向。同时有k个障碍点,要求走的路径不能经过这k个障碍点,字典序升序输出所有满足要求的路径序列以及最后的整数。
解法:
1. 要注变向时必须要变九十度,所以每次往下走的时候其实只有两个选择
2. 因为坐标可能为负数所以要将原点进行平移,因为走的距离最远是(1+n)*n/2,所以平移105即可。
代码如下:
#include<cstdio>
#include<string.h>
#include<cmath>
using namespace std;
const int maxn = 210;
int dst = 105;
//FILE*fp = fopen("stdout.txt", "w");
const char dict[] = "ensw";
const int dr[4] = { 1,0,0,-1 };
const int dc[4] = { 0,1,-1,0 };
int g[maxn][maxn], vis[maxn][maxn];
int ans[maxn], remain[maxn], sum;
int n, k;
void init() {
int sum = n*(1 + n) / 2;
remain[1] = sum;
for (int i = 2; i <= n; i++) {
remain[i] = remain[i - 1] - i + 1;
}
}
bool judge(int x,int y,int i,int cur) {
for (int j = 0; j < cur; j++) {
x = x + dr[i];
y = y + dc[i];
if (x < 0 || x >= maxn || y < 0 || y >= maxn)return false;
if (g[x][y] == 1)return false;
}
if (vis[x][y] == 1)return false;
else return true;
}
//位置x、位置y、走第几次了、不能走哪个方向
void dfs(int x,int y, int cur, int cant) {
if (cur == n+1) {
if (x == 105 && y == 105) {
for (int i = 1; i <= n; i++) {
printf("%c", dict[ans[i]]);
}printf("
");
sum++;
}
return;
}
if (abs(x - dst) + abs(y - dst) > remain[cur])return;
for (int i = 0; i < 4; i++) {
if (i == cant || i + cant == 3)continue;
int nx = x + cur*dr[i];
int ny = y + cur*dc[i];
if (judge(x,y,i,cur)) {
ans[cur] = i; vis[nx][ny] = 1;
dfs(nx, ny, cur + 1, i);
vis[nx][ny] = 0;
}
}
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
memset(ans, -1, sizeof(ans));
sum = 0;
scanf("%d", &n);
scanf("%d", &k);
int x, y;
for (int i = 0; i <= maxn; i++) {
memset(g[i], 0, sizeof(g[i]));
memset(vis[0], 0, sizeof(vis[i]));
}
while (k--) {
scanf("%d %d", &x, &y);
g[x + 105][y + 105] = 1;
}
init();
dfs(105, 105, 1, 5);
printf("Found %d golygon(s).
", sum);
}
return 0;
}