博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
刷题板块
阅读量:4589 次
发布时间:2019-06-09

本文共 4164 字,大约阅读时间需要 13 分钟。

题意:
输入n个结点的无向图及某个节点k,字典序升序输出n到k的所有道路,不可重复经过结点

题解:

dfs裸搜会T,所以需要每次搜索的时候都判断一下搜索的这个节点与目的节点能否联通,这里用并查集实现这个功能,若两个结点在同一集合中就表示为联通

代码如下:

#include
#include
#include
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\n", 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:\n", ++kase); if (findSet(k) != findSet(1)) { printf( "There are %d routes from the firestation to streetcorner %d.\n", 0, k); continue; } if (k == 1) { printf( "1\nThere are 1 routes from the firestation to streetcorner %d.\n", 1, k); continue; } dfs(1,0); printf("There are %d routes from the firestation to streetcorner %d.\n", tot, k); } //fclose(fp); return 0;}

题意:
平面上有n个障碍点,从(0,0)出发,要求走n步回到起点,第n次需要走的距离为n。每次必须要转九十度变向。同时有k个障碍点,要求走的路径不能经过这k个障碍点,字典序升序输出所有满足要求的路径序列以及最后的整数。

解法:

1. 要注变向时必须要变九十度,所以每次往下走的时候其实只有两个选择
2. 因为坐标可能为负数所以要将原点进行平移,因为走的距离最远是(1+n)*n/2,所以平移105即可。

代码如下:

#include
#include
#include
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("\n"); 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).\n\n", sum); } return 0;}

转载于:https://www.cnblogs.com/romaLzhih/p/9489814.html

你可能感兴趣的文章
Linux常用配置选项
查看>>
liunx加载JX2410标准配置文件
查看>>
Linux内核移植主要过程
查看>>
常用Linux文件系统
查看>>
Linux内核移植的若干问题
查看>>
linux程序对比
查看>>
linux数码管驱动程序和应用程序
查看>>
linux在菜单中添加SEG选项
查看>>
linux物理地址和虚拟地址
查看>>
linux驱动程序与菜单关联
查看>>
linux在配置菜单中添加选项
查看>>
linux修改文件系统注册设备
查看>>
linux添加地址映射
查看>>
c#程序集
查看>>
Microsoft 中间语言
查看>>
.NET Framework 简介
查看>>
c#通用语言运行时CLR
查看>>
编译和执行 C# 应用程序
查看>>
c#命名空间
查看>>
c#字面量
查看>>