标签:
TEXT里简单介绍了一下图论和Flood Fill Algorithms,感觉还是很有意义的,可以看看,http://www.wzoi.org/usaco/也是比较正常的翻译了,看起来不是机翻
The Castle
http://www.wzoi.org/usaco/12%5C105.asp
大致就是给你一个矩阵,依次描述每个点四面的墙的情况,点点可达到联通成一个房间,有墙不能穿过,问:
有多少个房间?
最大的房间的大小
删去一面墙后最大房间是多少?删去哪个墙?
简单BFS,标记点就可以,应该就是FF的应用吧。
处理四边走的方向的时候加上位运算就比较方便patpat。所以GO数组的顺序要讲究。
搜索的过程中可以得到每个房间的大小。选最大即第二个问题的解
第三个问题:枚举每个点的每个方向,如果该方向上有墙,且墙的另一边属于的房间不同就处理
第四个问题要求最靠西,最靠南 所以枚举的时候加个条件或者换一下枚举的顺序就可以了。
#include <bits/stdc++.h> using namespace std; const int N = 55; int n, m; int gox[4] = {0, -1, 0, 1}; int goy[4] = {-1, 0, 1, 0}; int op[N][N], Size[N*N], vis[N][N]; int id = 0; struct point{ int x, y; point(){}; point(int _x, int _y){ x = _x; y = _y; } }; bool outmap(int x, int y){ return x < 1 || y < 1 || x > n || y > m; } void bfs(int x, int y){ int xx, yy, i; queue<struct point>q; q.push(point(x , y)); point a; vis[x][y] = ++id; Size[id] = 1; while(!q.empty()){ a = q.front(); q.pop(); x = a.x; y = a.y; for(i = 0 ;i < 4; i++){ if(op[x][y] &(1<<i)) continue; xx = gox[i] + x; yy = goy[i] + y; if(outmap(xx, yy))continue; if(vis[xx][yy])continue; vis[xx][yy] = id; Size[id] ++; q.push(point(xx, yy)); } } } int main() { freopen("castle.in","r",stdin); #ifndef poi freopen("castle.out","w",stdout); #endif int i, j, k, x, y; scanf("%d%d", &m, &n); for(i = 1; i <= n; i++){ for(j = 1; j <= m; j++){ scanf("%d",&op[i][j]); } } for(i = 1; i <= n; i++){ for(j = 1; j <= m; j++){ if(vis[i][j]) continue; bfs(i, j); } } int ans = 0, maxroom = 0, posx, posy, posdir; for(i = 1; i <= n; i++){ for(j = 1; j <= n; j++){ maxroom = max(maxroom, Size[vis[i][j]]); for(k = 0; k < 4; k++){ if(op[i][j]&(1<<k)){ x = i + gox[k];y = j + goy[k]; if(outmap(x, y)) continue; if(vis[i][j] == vis[x][y])continue; int temp = Size[vis[x][y]] + Size[vis[i][j]]; if(temp > ans){ posx = i; posy = j; posdir = k; ans = temp; } else if(temp == ans){ // cout << ans << " " << i << " "<<j <<endl; if(j < posy || (j == posy && i > posx)){ posx = i; posy = j; posdir = k; } } } } } } cout << id <<endl<<maxroom <<endl << ans << endl ; cout << posx <<" "<<posy <<" "; switch(posdir){ case 0: cout << "W"<<endl; break; case 1: cout << "N"<<endl; break; case 2: cout << "E" << endl; break; case 3: cout << "S" <<endl; break; } return 0; }
Ordered Fractions
按顺序输出分母<=N的所有既约真分数
题解的标准方法是搜索,但是我爆搞了= =
枚举分母,据此枚举分子,用gcd判断是否互素,再排序。
排序的时候用分母分子相乘而不是变成小数的方法来保证精度。
#include <bits/stdc++.h> using namespace std; struct point{ int x, y; point(){}; point(int _x, int _y){x = _x, y = _y;}; bool operator<(const point &I)const{ if(y == I.y)return x <I.x; return x*I.y < y * I.x; } }; vector<struct point>ans; int main() { freopen("frac1.in","r",stdin); #ifndef poi freopen("frac1.out","w",stdout); #endif int n, i, j; cin >> n; ans.push_back(point(0, 1)); ans.push_back(point(1, 1)); for(i = 2; i <= n; i++){ for(j = 1; j < i; j++){ if(__gcd(i, j) != 1) continue; ans.push_back(point(j, i)); } } sort(ans.begin(), ans.end()); for(i = 0; i < ans.size(); i++){ printf("%d/%d\n", ans[i].x, ans[i].y); } return 0; }
Sorting a Three-Valued Sequence
很有趣的题patpat
给出一堆由1 2 3组成的序列,交换两个数为一次操作,问最少需要多少次操作可以使得序列有序
输入的时候可以处理出多少个1 2 3
如果1的位置在前num[1]个就不用交换,同理23
故扫一次可以扫出有多少个1放在了应该是2在的地方,多少个2在1的地方之类的,用二维数组描述。所有的位置不对的数目为sum
如果1占了2的位置2占了1的位置,把他们交换一次即可使sum -=2
同理13 23.
当他们互相之间的占领关系形成一个环,则需要交换两次使sum-=3
所以先搞完所有一次交换的,sum-2*交换次数则为需要交换两次的。
#include <bits/stdc++.h> using namespace std; const int N = 1004; int a[N]; int num[4]; int disor[4][4]; int main() { freopen("sort3.in","r",stdin); #ifndef poi freopen("sort3.out","w",stdout); #endif int i, j, n, ans, sum = 0; scanf("%d", &n); for(i = 1; i <= n; i++){ scanf("%d", &a[i]); num[a[i]] ++; } for( i = 1; i <= num[1]; i++){ disor[1][a[i]] ++; if(a[i] != 1) sum ++; } for( ; i <= num[1] + num[2]; i++) { disor[2][a[i]] ++; if(a[i] != 2) sum ++; } for(; i <= n; i++){ disor[3][a[i]] ++; if(a[i] != 3) sum ++; } //cout << sum << endl; ans = min(disor[3][1], disor[1][3]) + min(disor[2][3], disor[3][2]) + min(disor[1][2] , disor[2][1]); //cout <<ans <<endl; ans = (sum - ans*2) * 2 / 3 + ans; cout << ans<<endl; return 0; }
Healthy Holsteins
http://www.wzoi.org/usaco/15%5C101.asp
状压+广搜写的。从二进制中只有一个1的往队列里加,这样自然是让他用的饲料种类最少
#include <bits/stdc++.h> using namespace std; const int N = 30; const int M = 40000; int dis[M], f[N][N], need[N], get[N]; int n, m; vector<int>ans; bool check(int x){ int i, j; memset(get, 0, sizeof(get)); for(i = 1; i <= n; i++){ if(x & (1 << (i-1))){ for(j = 1; j <= m; j++){ get[j] += f[i][j]; } } } for(j = 1; j <= m; j++){ // printf("%d %d\n",x, get[j]); if(need[j] > get[j])return false; } return true; } int bfs(int &state){ int i, j, x, y; queue<int>q; q.push(0); dis[0] = 1; while(!q.empty()){ x = q.front(); q.pop(); for(i = 1; i <= n; i++){ if(x&(1<<(i-1))) continue; y = (x |1<<(i-1)); if(dis[y]) continue; dis[y] = dis[x] + 1; if(check(y)){ state = y; return dis[y]; } // cout << y<<endl; q.push(y); } } } int main() { freopen("holstein.in","r",stdin); #ifndef poi freopen("holstein.out","w",stdout); #endif int i, j; scanf("%d", &m); for(i = 1; i <= m; i++) scanf("%d", &need[i]); scanf("%d", &n); for(i = 1; i <= n; i++) for(j = 1; j <= m; j++) scanf("%d", &f[i][j]); int state; int ans = bfs(state); cout << ans - 1; for(i = 1; i <= n; i++){ if(state & (1 << (i-1)))cout <<" " << i; } cout << endl;return 0; }
Hamming Codes
http://www.wzoi.org/usaco/15%5C311.asp
要使最小,故从小到大枚举。
只要与已经选出的数都符合条件,就选中。
处理两个数差异的方法是i^j,然后gao之
这是上一节讲的位运算的方法,放在这里难道是艾宾浩斯?
#include <bits/stdc++.h> using namespace std; const int N = 400; int dis[N]; int ans[N]; int gao(int x){ int num = 0; while(x){ num += (x & 1); x >>= 1; } return num; } int main() { freopen("hamming.in","r",stdin); #ifndef poi freopen("hamming.out","w",stdout); #endif dis[0] = 0; int n, b, d, limit, id = 1, row = 1, i, j; cin >> n >> b >> d; limit = 1 << b; for(i = 1; i < limit; i++){ dis[i] = gao(i); } ans[1] = 0; cout << 0; for(i = 1; i < limit; i++){ for(j = 1; j <= id; j++){ // cout << i << " " <<ans[j] << " " <<gao(i ^ ans[j]) << endl; if(gao(i^ans[j])< d) break; } if(j == id + 1) { ans[++id] = i; if(row == 10){ cout << endl<< i; row = 1; }else { row ++; cout << " " << i; } if(id == n) break; } } cout << endl; return 0; }
在图书馆的计算机架子上,看到好多的计算机方面的书。。。好想看,不想回学校了。。。
寒假考研结束泡图书馆吧patpat
标签:
原文地址:http://www.cnblogs.com/bbbbbq/p/4652916.html