一、安排
学数据结构和图论时,也就上课听了一点,课后没复习也没做题。真是一点都没印象了,今天看了几道最小生成树的题,复习了一下课件,查了一下知识点。‘
二、题目
1、Curling 2.0
找最短步数,一开始以为是个bfs,程序写好了一大半,结果发现好像有点不对,朝着特定方向搜索,应该是dfs?果真dfs可以实现,但是需要考虑的条件有点多,一开始还写的漏了好几个条件。
# include <cstdio> # include <iostream> # include <cstring> using namespace std; #define inf 0x7fffffff int sx,sy, re; int m, n; int mp[25][25]; int dir[4][2] = { {-1, 0}, {1, 0}, {0, 1}, {0, -1} };
void dfs(int nowx,int nowy,int step) { step++; if(step > 10) return; for(int i = 0; i < 4; i++) { int nextx = nowx + dir[i][0]; int nexty = nowy + dir[i][1]; if(mp[nextx][nexty] == 1) continue; while(mp[nextx][nexty] == 0 || mp[nextx][nexty] == 2) { nextx += dir[i][0]; nexty += dir[i][1]; } if(mp[nextx][nexty] < 0) continue; if(mp[nextx][nexty] == 1) { mp[nextx][nexty] = 0; dfs(nextx - dir[i][0], nexty - dir[i][1], step); mp[nextx][nexty] = 1; }
if(mp[nextx][nexty] == 3) { if(step < re) re = step; continue; } } } int main() { while(~scanf("%d%d", &m, &n) && (m || n)) { re = inf; memset(mp, -1, sizeof(mp)); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) { cin >> mp[i][j]; if(mp[i][j] == 2) { sx = i; sy = j; } } dfs(sx, sy, 0); if(re < inf) cout << re << endl; else cout << -1 << endl;; } return 0; }
2、Shredding Company
分隔数字后相加,使其最接近并小于目标数。深搜。
#include <stdio.h> #include <string.h> #include <iostream> using namespace std;
char str[10]; int t, n, max_sum, step_sum; int v[10], vi[10]; int dis[1000000];
void dfs(int xi, int sum, int step)//xi记录进行了多少长度,sum记录和,step记录分了几部分; { int i; int flag; if(xi >= n) { flag = 1; for(i = 0; i < step; i++)//与现有最优解进行对比是否相同 { if(v[i] != vi[i]) { flag = 0; break; } } if(flag == 0)//不相同就记录下来 { dis[sum] ++; } if(sum > max_sum)//寻找最优解 { max_sum = sum; step_sum = step; for(i = 0; i < step; i++) { vi[i] = v[i]; } } return; } int sum1 = 0; for(i = xi; i < n; i++) { sum1 = sum1*10 + str[i] - '0'; if(sum1 + sum <= t) { v[step] = sum1;//记录每一段的数值 dfs(i+1, sum1 + sum, step+1); } else break; } }
int main() { int i; while(~scanf("%d%s", &t, str)) { memset(v, 0, sizeof(v)); memset(vi, 0, sizeof(vi)); memset(dis, 0, sizeof(dis)); if(t==0 && strcmp(str, "0")==0) break; n = strlen(str); int s = 0; for(i = 0; i < n; i++) { s += str[i] - '0'; } if(s > t) { printf("error\n"); continue; } max_sum = 0; step_sum = 0; dfs(0, 0, 0); if(dis[max_sum] != 1) { printf("rejected\n"); } else { printf("%d",max_sum); for(i = 0; i < step_sum; i++) { printf(" %d", vi[i]); } printf("\n"); } } return 0; }
3、Highways
最小生成树的问题,这个一开始做的,没有用prim算法,这种思路也是可以接受的。但是一样的算法,在做下一题时WA了,完全不知道为什么。这个整整纠结了一下午,真心是一样的题,只是输出的结果不同。
后来比较了一下,还是prim算法简单,以后还是用prim算法吧
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;
int mp[521][521]; int parent[521],high[521];
struct Node { int x,y; int data; }node[125011];
bool cmp(Node a,Node b) { return a.data<b.data; }
int Find(int m) { if(m==parent[m]) return m; else return parent[m]=Find(parent[m]); }
void unite(int x,int y) { int fx,fy; fx=Find(x); fy=Find(y); if(fx==fy) //两点已经连通,返回 return ; if(high[fx]<high[fy]) //比较两根节点目前所在树的高度 ,低的连在高的上面,一样高则任意一个加一 parent[fx]=fy;
else { parent[fy]=fx; if(high[fx]==high[fy]) high[fx]++; } }
int main() { int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&mp[i][j]); for(int i=1;i<=n;i++) { parent[i]=i; high[i]=0; }//初始化父节点和树的高度 int k=0,ans=0; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { node[k].x=i; node[k].y=j; node[k].data=mp[i][j]; k++; } }//建树 sort(node,node+k,cmp); for(int i=0;i<k;i++) { if(Find(node[i].x)!=Find(node[i].y)) { ans=max(ans,node[i].data); unite(node[i].x,node[i].y); } } printf("%d",ans); } return 0; }
4、Agri-Net
这个是用prim算法解决的
#include<iostream> #include<cstring> #include<cstdio> using namespace std;
int node[101][101],vis[101],lowcost[101],n;
void prim() { int next,Min,sum; sum=0; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) lowcost[i]=node[1][i]; vis[1]=1; for(int i=2;i<=n;i++) { Min=1000001; for(int j=1;j<=n;j++) { if(!vis[j]&&Min>lowcost[j]) { Min=lowcost[j]; next=j; } } sum+=Min; vis[next]=1; for(int j=1;j<=n;j++) { if(!vis[j]&&lowcost[j]>node[next][j]) lowcost[j]=node[next][j]; } } printf("%d\n",sum); }
int main() { while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&node[i][j]); prim(); } }