Codeforces Round #192 (Div. 2)
A:
題意:
給出一個矩陣表示蛋糕,矩陣中有毒草莓。我們每次可以選擇一行或者一列來吃蛋糕,要保證改行該列不含有毒草莓。問我們能吃到的最多的小蛋糕快
思路:
直接枚舉每一行,每一列然后吃,模擬就行。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue>#define CL(arr, val) memset(arr, val, sizeof(arr))#define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout);#define M 1007 #define N 1007 using namespace std;int n,m; char str[N][N]; bool vt[N][N];int main() { // Read(); cin>>n>>m;CL(vt,false);for (int i = 0; i < n; ++i){scanf("%s",str[i]);}int ans = 0;for (int i = 0; i < n; ++i){int f = 1;int tmp = 0;for (int j = 0; j < m; ++j){if (str[i][j] == 'S') f = 0;else if (!vt[i][j]) tmp++;}if (f == 1){ans += tmp;for (int j = 0; j < m; ++j){vt[i][j] = true;}}}for (int j = 0; j < m; ++j){int f = 1;int tmp = 0;for (int i = 0; i < n; ++i){if (str[i][j] == 'S') f = 0;else if (!vt[i][j]) tmp++;}if (f == 1){ans += tmp;for (int i = 0; i < n; ++i){vt[i][j] = true;}}}cout << ans << endl;return 0; } View Code?
B:
題意:
給你n個點,m條邊,m條邊表示不能連接在一起的邊。讓我們建立這樣一個圖,使得任意一個點都能通過至多兩條邊就能到達其他的任意點。 題目保證有解,數出這個圖的邊
思路:
不能再一起的點肯定是通過一個中間點連接的,然后我們把不能在一起的點放進一個set,(因為可能會出現重復的點,題目只是說不會出現重復的邊,比賽時理解錯了wa了一次)
然后找出一個不存在排他關系的點當做中間點,所有點都連接一條邊到他就好了。?
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue>#define CL(arr, val) memset(arr, val, sizeof(arr))#define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout);#define M 1007 #define N 1007 using namespace std;struct node {int u,v; }nd[N]; int len; bool vt[N];vector<int> vc; set<int> X; int n,m;int main() { // Read();cin>>n>>m;CL(vt,false); len = 0;int x,y;X.clear();for (int i = 1; i <= m; ++i){scanf("%d%d",&x,&y);if (!vt[x]) X.insert(x);if (!vt[y]) X.insert(y);vt[x] = true;vt[y] = true;}vc.clear();for (int i = 1; i <= n; ++i){if (!vt[i]) vc.push_back(i);}int ans = 0;ans += (vc.size() - 1 + X.size());cout << ans <<endl;int mid = vc[0];int sz = vc.size();for (int i = 1; i < sz; ++i){printf("%d %d\n",vc[i],mid);}set<int>::iterator it;for (it = X.begin(); it != X.end(); it++){printf("%d %d\n",*it,mid);}return 0; } View Code?
C:
題意:
給你一個矩陣,其中的每個單元都需要凈化,我們通過貼符的方式使得其在的行與列的所有的單元都會的到凈化,其中“.”表示可以貼符的單元,“E”表示不可以貼符的單元。 求使貼最少的符,使得所有的單元都被得到凈化。
思路:
我們分析可得,如果該矩陣的所有單元都得到凈化的話。必定是每一行都存在“.” 或者每一列都存在"." 否則是不行的。然后我們只要枚舉行,枚舉列模擬一下記錄“.”的位置就好了。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue>#define CL(arr, val) memset(arr, val, sizeof(arr))#define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define keyTree (chd[chd[root][1]][0]) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout);#define M 100 #define N 307using namespace std;int dx[4]={-1,1,0,0}; int dy[4]={0,0,-1,1};//иообвСсрconst int inf = 0x7f7f7f7f; const int mod = 1000000007; const double eps = 1e-8;int rv[N],cv[N]; int n; char str[N][N]; int a[N];int main() {scanf("%d",&n);for (int i = 0; i < n; ++i) scanf("%s",str[i]);CL(rv,0);for (int i = 0; i < n; ++i){for (int j = 0; j < n; ++j){if (str[i][j] == '.'){rv[i] = 1;a[i] = j;break;}}}int f = 1;for (int i = 0; i < n; ++i) if (!rv[i]) f = 0;if (f) for (int i = 0; i < n; ++i) cout << i + 1 << " " << a[i] + 1 << endl;else{CL(cv,0); f = 1;for (int j = 0; j < n; ++j){for (int i = 0; i < n; ++i){if (str[i][j] == '.'){cv[j] = 1;a[j] = i;break;}}}for (int j = 0; j < n; ++j) if (!cv[j]) f = 0;if (f) for (int j = 0; j < n; ++j) cout << a[j] + 1 << " " << j + 1 << endl;else printf("-1\n");}return 0; } View Code?
D:
題意:
給你一個矩陣,其中“T”表示樹,“S”表示你的起點,“0 - 9”表示擁有該數量的團伙的敵人,“E”表示目的地,你的目標是移動到E,但是在你移動的過程中會有敵人一伙一伙的來找你,與你PK,當你們相遇時你必須PK掉所有的敵人才可以繼續往下走。我們不管你走了多少步。我們只需要知道你在到達目的地的過程中最少的PK掉的人數。
思路:
所有的人同時向目標移動,移動的過程誰會碰到我呢,怎么判斷呢? 分析可知道,只要某個人到達終點的最短距離小于等于我倒終點的最短距離的,一定會趕上我與我PK,然后我們只要利用spfa求出終點到每個點的最短距離,然后檢查到達其他點的最短距離小于我的就加上即可。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue>#define CL(arr, val) memset(arr, val, sizeof(arr))#define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define keyTree (chd[chd[root][1]][0]) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout);#define M 100 #define N 1007using namespace std;int dx[4]={-1,1,0,0}; int dy[4]={0,0,-1,1};//иообвСсрconst int inf = 0x7f7f7f7f; const int mod = 1000000007; const double eps = 1e-8;struct node {int x,y;int stp;node(int tx = 0,int ty = 0,int ts = 0) : x(tx),y(ty),stp(ts) {} };char str[N][N]; int dis[N][N]; bool vt[N][N]; int n,m; int len; int sx,sy;int inmap(int x,int y) {if (x >= 0 && x < n && y >= 0 && y < m) return true;return false; } void spfa() {queue<node> q;for (int i = 0; i < n; ++i){for (int j = 0; j < m; ++j){if (str[i][j] == 'E'){dis[i][j] = 0;vt[i][j] = true;q.push(node(i,j,0));}else{dis[i][j] = inf;vt[i][j] = false;}}}while (!q.empty()){node u = q.front(); q.pop();for (int i = 0; i < 4; ++i){int tx = u.x + dx[i];int ty = u.y + dy[i];if (!inmap(tx,ty)) continue;if (str[tx][ty] == 'T') continue;if (dis[tx][ty] > u.stp + 1){dis[tx][ty] = u.stp + 1;if (!vt[tx][ty])q.push(node(tx,ty,dis[tx][ty]));}}vt[u.x][u.y] = false;} } int main() {cin>>n>>m;for (int i = 0; i < n; ++i){scanf("%s",str[i]);for (int j = 0; j < m; ++j){if (str[i][j] == 'S'){sx = i; sy = j;}}}spfa();int ans = 0;int tmp = dis[sx][sy];for (int i = 0; i < n; ++i){for (int j = 0; j < m; ++j){ // printf("%c %d\n",str[i][j],dis[i][j]);if (str[i][j] >= '1' && str[i][j] <= '9' && dis[i][j] <= tmp){ans += str[i][j] - '0';}}}printf("%d\n",ans);return 0; } View Code?
E:
題意:
給你一個n個點,m條邊的無向圖,然后讓你重新構圖,使得舊圖中的邊不會存在于新圖。然后舊圖與新圖都必須滿足每個點至多有兩條邊與其相連,兩圖的點的個數也必須相同。
思路:
首先不會存在重復的邊,然后每個點至多有兩條邊與其相連。 該圖一定是連續的鏈,或者一個一一排列的環的組和。 我們重新構建之后以肯定也是這樣的。 所以我們只要保存起來不能存在于新圖的邊,然后利用隨機函數?random_shuffle()的到1-n的一個排列,然后檢查按照該順序建邊是否能夠建造出滿足條件的圖,如果可以直接輸出就好了。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue>#define CL(arr, val) memset(arr, val, sizeof(arr))#define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define keyTree (chd[chd[root][1]][0]) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout);#define M 100 #define N 100007using namespace std;int dx[4]={-1,1,0,0}; int dy[4]={0,0,-1,1};//иообвСсрconst int inf = 0x7f7f7f7f; const int mod = 1000000007; const double eps = 1e-8;int n,m; int id[N];set<pair<int,int> > st;bool solve() {for (int i = 1; i <= n; ++i) id[i] = i;random_shuffle(id + 1,id + 1 + n);id[n + 1] = id[1];int cnt = 0;for (int i = 2; i <= n + 1; ++i){if (st.find(make_pair(id[i - 1],id[i])) == st.end()) cnt++;}if (cnt < m) return false;for (int i = 2; i <= n + 1 && m; ++i){if (st.find(make_pair(id[i - 1],id[i])) == st.end()){printf("%d %d\n",id[i - 1],id[i]);m--;}}return true; } int main() {scanf("%d%d",&n,&m);int x,y;st.clear();for (int i = 0; i < m; ++i){scanf("%d%d",&x,&y);st.insert(make_pair(x,y));st.insert(make_pair(y,x));}for (int i = 0; i < 100; ++i){if (solve()) return 0;}printf("-1\n");return 0; } View Code?
還有一種做法就是dfs我們按照點從小到大的順序枚舉,然后不斷的往后檢查符合條件的點,直到我們找到符合條件的邊,這個過程中記錄我們枚舉到的邊,然后利用set處理枚舉可能會出現重復遍點的問題。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue>#define CL(arr, val) memset(arr, val, sizeof(arr))#define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define keyTree (chd[chd[root][1]][0]) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout);#define M 100 #define N 100007using namespace std;int dx[4]={-1,1,0,0}; int dy[4]={0,0,-1,1};//懈芯芯斜脅小褋褉const int inf = 0x7f7f7f7f; const int mod = 1000000007; const double eps = 1e-8;int n,m; set<int> v; vector< pair<int,int> > ans; vector<int> vc[N]; bool isok(int u,int v) {for (size_t i = 0; i < vc[u].size(); ++i){if (vc[u][i] == v) return false;}return true; } bool dfs(int u) {if ((int)ans.size() == min(n - 1,m)) return true;v.erase(u);for (set<int>::iterator it = v.begin(); it != v.end(); ++it){if (!isok(u,*it)) continue;ans.push_back(make_pair(u,*it));if (dfs(*it)) return true;else{ans.pop_back();it = v.find(*it);//注意這里一定要重新定位it的值,//雖然后邊的點都插進來了,而且是按順序,但是it++的地址已經變了//如果不重新定位的話訪問的將不是我們想要的值 }}v.insert(u);return false; } int main() {scanf("%d%d",&n,&m);for (int i = 0; i <= n; ++i) vc[i].clear();int x,y;for (int i = 0; i < m; ++i){scanf("%d%d",&x,&y);vc[x].push_back(y);vc[y].push_back(x);}for (int i = 1; i <= n; ++i) v.insert(i);ans.clear();for (int i = 1; i <= n; ++i){if (dfs(i)){if (m == n) ans.push_back(make_pair(ans[0].first,ans.back().second));for (int i = 0; i < m; ++i) printf("%d %d\n",ans[i].first,ans[i].second);return 0;}}printf("-1\n");return 0; } View Code?
?
?
總結
以上是生活随笔為你收集整理的Codeforces Round #192 (Div. 2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 工程数学概率论统计简明教程第二版复习大纲
- 下一篇: 【电路补习笔记】4、二极管的参数与选型