1、連通性
給定一個方陣,定義連通:上下左右相鄰,並且值相同。
可以想象成一張地圖,不同的區域被塗以不同顏色。輸入:
整數N, (N<50)表示矩陣的行列數
接下來N行,每行N個字符,代表方陣中的元素
接下來一個整數M,(M<1000)表示詢問數
接下來M行,每行代表一個詢問,
格式爲4個整數,y1,x1,y2,x2,
表示(第y1行,第x1列) 與 (第y2行,第x2列) 是否連通。
連通輸出true,否則false
例如:
10
0010000000
0011100000
0000111110
0001100010
1111010010
0000010010
0000010011
0111111000
0000010000
0000000000
3
0 0 9 9
0 2 6 8
4 4 4 6
程序應該輸出:
false
true
true
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <utility>
using namespace std;
typedef pair<int, int> loc;
int visit[51][51];
int f(char (*aa)[51], loc a, loc b, int c){
if(a.first == b.first && a.second == b.second){
return 1;
}
int dy[] = {0, 0, 1, -1};
int dx[] = {1, -1, 0, 0};
for(int i = 0; i < 4; i++){
int ey = a.first + dy[i];
int ex = a.second + dx[i];
if(ex >= 0 && ex < c && ey >= 0 && ey < c
&& visit[ey][ex] == 0 && aa[ey][ex] == aa[a.first][a.second]){
visit[ey][ex] = 1;
loc g(ey, ex);
if(f(aa, g, b, c)){
return 1;
}
}
}
return 0;
}
int main(){
freopen("input.txt", "r", stdin);
char a[51][51];
int b;
// cin >> b;
cout << b << endl;
for(int i = 0; i < b; i++){
cin >> a[i];
}
// for(int i = 0; i < b; i++){
// for(int j = 0; j < b; j++){
// cout << a[i][j] << " ";
// }
// cout << endl;
// }
int c;
cin >> c;
// cout << c << endl;
loc d[2002];
for(int i = 0; i < 2 * c; i++){
cin >> d[i].first >> d[i].second;
// cout << d[i].first << d[i].second << endl;
}
for(int i = 0; i < 2 * c; i += 2){
for(int j = 0; j < 51; j++){
for(int k = 0; k < 51; k++){
visit[j][k] = 0;
}
}
if(f(a, d[i], d[i + 1], b) == 1){
cout << "true" << endl;
}
else{
cout << "false" << endl;
}
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
int f(char map[][54], int len, int y1, int x1, int y2, int x2){
if(y1 == y2 && x1 == x2){
return 1;
}
for(int i = 0; i < 4; i++){
int y3 = y1 + dy[i];
int x3 = x1 + dx[i];
char old;
old = map[y1][x1];
if(y3 >= 0 && y3 < len
&& x3 >= 0 && x3 < len){
map[y1][x1] = '*';
if(map[y3][x3] == old && f(map, len, y3, x3, y2, x2)){
map[y1][x1] = old;
return 1;
}
}
map[y1][x1] = old;
}
return 0;
}
int main(){
FILE * in;
FILE * out;
in = fopen("in.txt", "r");
out = fopen("out.txt", "w");
char m1[4];
int m2; // 矩陣邊長
fgets(m1, 4, in);
sscanf(m1, "%d", &m2);
fprintf(out, "%d\n", m2);
char map[54][54];
for(int i = 0; i < m2; i++){
fgets(map[i], m2 + 2, in);
}
for(int i = 0; i < m2; i++){
fprintf(out, "%s", map[i]);
}
char n1[7];
int n2;
fgets(n1, 5, in);
sscanf(n1, "%d", &n2);
char test[1002][4];
char test2[10];
fprintf(out, "%d\n", n2);
for(int i = 0; i < n2; i++){
fgets(test2, 10, in);
sscanf(test2, "%d %d %d %d", &test[i][0], &test[i][1], &test[i][2], &test[i][3]);
fprintf(out, "%d %d %d %d\n", test[i][0], test[i][1], test[i][2], test[i][3]);
int re = f(map, m2, test[i][0], test[i][1], test[i][2], test[i][3]);
fprintf(out, "%s\n", re == 1 ? "true": "false");
}
}
2、迷宮問題
...11111111111111111111111111111
11.111111........1111111111.1111
11.111111..111.11111111.....1111
11.11111111111.1111111111.111111
11.111111.................111111
11.111111.11111111111.11111.1111
11.111111.11111111111.11111..111
11.................11.11111.1111
11111.111111111111.11.11....1111
11111.111111111111.11.11.11.1111
11111.111111111111.11.11.11.1111
111...111111111111.11.11.11.1111
111.11111111111111.11....11.1111
111.11111111111111.11111111.1111
111.1111.111111111.11111......11
111.1111.......111.11111.1111.11
111.1111.11111.111.11111.1111.11
111......11111.111.11111.1111111
11111111111111.111.11111.111...1
11111111111111...............1.1
111111111111111111111111111111..
"1"是牆壁,"."是通路
求最短需要走多少步?
#include <iostream>
#include <utility>
#include <vector>
using namespace std;
typedef pair<int, int> loc;
vector<loc> v;
void show(){
for(int i = 0; i < v.size(); i++){
loc a = v.at(i);
cout <<"(" << a.first <<","<< a.second <<")";
}
cout << endl << endl;
}
int visit[22][35];
int f(char (*aa)[33], loc a){
visit[0][0] = 1;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
v.push_back(a);
int n = 0;
while(!v.empty()){
// show();
loc c = v.front();
v.erase(v.begin());
// cout <<"erase";
// show();
n = 0;
int ex, ey;
for(int i = 0; i < 4; i++){
ex = c.second + dx[i];
ey = c.first + dy[i];
if(ey >= 0 && ey < 22 && ex >= 0 && ex < 32
&& aa[ey][ex] == '.' && visit[ey][ex] == 0){
n++;
visit[ey][ex] = visit[c.first][c.second] + 1;
loc h(ey, ex);
v.push_back(h);
}
}
}
return visit[20][31];
}
int main(){
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
char a[22][33];
for(int i = 0; i < 21; i++){
cin >> a[i];
}
for(int i = 0; i < 21; i++){
cout << a[i] << endl;
}
cout << f(a, loc(0, 0)) << endl;
// for(int i = 0; i < 22; i++){
// for(int j = 0; j < 32; j++){
// printf("%3d", visit[i][j]);
// }
// cout << endl;
// }
}
3、分酒問題
有4個紅酒瓶子,它們的容量分別是:9升, 7升, 4升, 2升
開始的狀態是 [9,0,0,0],也就是說:第一個瓶子滿着,其它的都空着。
允許把酒從一個瓶子倒入另一個瓶子,但只能把一個瓶子倒滿或把一個瓶子倒空,不能有中間狀態。
這樣的一次倒酒動作稱爲1次操作。
假設瓶子的容量和初始狀態不變,對於給定的目標狀態,至少需要多少次操作才能實現?
本題就是要求你編程實現最小操作次數的計算。
輸入:最終狀態(空格分隔)
輸出:最小操作次數(如無法實現,則輸出-1)
例如:
輸入:
9 0 0 0
應該輸出:
0
輸入:
6 0 0 3
應該輸出:
-1
輸入:
7 2 0 0
應該輸出:
2
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int> vv;
vector<string> v;
int f1(string a){
int b[] = {9, 7, 4, 2};
int c[4];
for(int i = 0; i < 4; i++){
c[i] = a.at(i) - '0';
}
int d = 0;
int e = 0;
for(int i = 0; i < 4; i++){
d += c[i];
if(c[i] > b[i]){
e = 1;
}
}
if(d > 9 || e == 1){
return 0;
}
else{
return 1;
}
}
int f(string h, string b){
string a = h;
v.push_back(a);
vv.push_back(0);
int d[4];
int aa;
int e[4] = {9, 7, 4, 2};
cout << f1(b);
if(f1(b) == 0){
return -1;
}
while (!v.empty()){
a = v.front();
// cout << a << endl;
v.erase(v.begin());
aa = vv.front();
vv.erase(vv.begin());
if(a == b){
return aa;
}
for (int i = 0; i < 4; i++){
d[i] = a.at(i) - '0';
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
if(i == j) continue; //自己
if(d[i] == 0) continue; //自己爲空
if(d[j] == e[j]) continue; //要倒的爲滿
int h1, h2;
h1 = d[i];
h2 = d[j];
if(d[i] + d[j] >= e[j]){
d[i] = d[i] - (e[j] - d[j]);
d[j] = e[j];
}
else{
d[j] += d[i];
d[i] = 0;
}
a = "";
for(int i = 0; i < 4; i++){
a += d[i] + '0';
}
v.push_back(a);
vv.push_back(aa + 1);
d[i] = h1;
d[j] = h2;
}
}
}
return -1;
}
int main()
{
string a = "6003";
cout << f("9000", a);
}
4、風險度量
標題:風險度量
X星系的的防衛體系包含 n 個空間站。這 n 個空間站間有 m 條通信鏈路,構成通信網。
兩個空間站間可能直接通信,也可能通過其它空間站中轉。
對於兩個站點x和y (x != y), 如果能找到一個站點z,使得:
當z被破壞後,x和y不連通,則稱z爲關於x,y的關鍵站點。
顯然,對於給定的兩個站點,關於它們的關鍵點的個數越多,通信風險越大。
你的任務是:已經網絡結構,求兩站點之間的通信風險度,即:它們之間的關鍵點的個數。
輸入數據第一行包含2個整數n(2 <= n <= 1000), m(0 <= m <= 2000),分別代表站點數,鏈路數。
空間站的編號從1到n。通信鏈路用其兩端的站點編號表示。
接下來m行,每行兩個整數 u,v (1 <= u, v <= n; u != v)代表一條鏈路。
最後1行,兩個數u,v,代表被詢問通信風險度的兩個站點。
輸出:一個整數,如果詢問的兩點不連通則輸出-1.
用戶輸入:
7 6
1 3
2 3
3 4
3 5
4 5
5 6
1 6
則程序應該輸出:
2
資源約定:
峯值內存消耗(含虛擬機) < 256M
CPU消耗 < 2000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多餘內容。
所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。
java選手注意:不要使用package語句。不要使用jdk1.7及以上版本的特性。
java選手注意:主類的名字必須是:Main,否則按無效代碼處理。
c/c++選手注意: main函數需要返回0
c/c++選手注意: 只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操作系統的特殊函數。
c/c++選手注意: 所有依賴的函數必須明確地在源文件中 #include <xxx>, 不能通過工程設置而省略常用頭文件。
提交程序時,注意選擇所期望的語言類型和編譯器類型。
#include <iostream>
#include <list>
#include <vector>
#include <string>
using namespace std;
void f1(int re[][4], int a, int b){
if(re[a][3] > b){
re[a][3] = b;
f1(re, re[a][1], b);
}
}
void f(vector<int> * c, int re[][4], int a, int b){
if(a == b){
return ;
}
for(int i = 0; i < c[a].size(); i++){
int d = c[a].at(i);
if(re[d][0] > 0){
f1(re, a, re[d][2]); //深度傳進去
continue;
}
re[d][0] = 1; //訪問標記
re[d][1] = a; //父親結點
re[d][2] = re[a][2] + 1; //深度
re[d][3] = re[a][2]; //返祖結點
f(c, re, d, b);
}
}
int f2(int re[][4], int a, int b){
int min = re[b][3];
int d = 0; //sum
while(true){
int c = re[b][1];
// cout << "father: " << c << endl;
if(c == a || c == -1) break;
if(re[c][2] <= min){
// cout << "c :" << c << endl;
d++;
}
if(re[c][3] < min){
min = re[c][3];
}
b = c;
}
return d;
}
int main(){
freopen("input.txt", "r", stdin);
int a; // 點數
int b; //邊數
vector<int> c[1002];
cin >> a >> b;
// cout << a << " " << b << endl;
for(int i = 0; i < b; i++){
int ba, bb;
cin >> ba >> bb;
// cout << ba << " " << bb << endl;
c[ba].push_back(bb);
c[bb].push_back(ba);
}
int ca, cb; //侍求點
cin >> ca >> cb;
// cout << ca << " " << cb << endl;
int re[1002][4]; // (訪問標記,父結點,深度,返祖標記)
re[ca][0] = 1;
re[ca][1] = -1;
re[ca][2] = 1;
re[ca][3] = -1;
f(c, re, ca, cb);
cout << f2(re, ca, cb) << endl;
// for(int i = 1; i < 7; i++){
// cout << i << " :";
// for(int j = 0; j < 4; j++){
// cout << re[i][j] << " ";
// }
// cout << endl;
// }
}
5、合根植物
w星球的一個種植園,被分成 m * n 個小格子(東西方向m行,南北方向n列)。每個格子裏種了一株合根植物。
這種植物有個特點,它的根可能會沿着南北或東西方向伸展,從而與另一個格子的植物合成爲一體。
如果我們告訴你哪些小格子間出現了連根現象,你能說出這個園中一共有多少株合根植物嗎?
輸入格式:
第一行,兩個整數m,n,用空格分開,表示格子的行數、列數(1<m,n<1000)。接下來一行,一個整數k,表示下面還有k行數據(0<k<100000)
接下來k行,第行兩個整數a,b,表示編號爲a的小格子和編號爲b的小格子合根了。
格子的編號一行一行,從上到下,從左到右編號。
比如:5 * 4 的小格子,編號:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 18 19 20
樣例輸入:
5 4
16
2 3
1 5
5 9
4 8
7 8
9 10
10 11
11 12
10 14
12 16
14 18
17 18
15 19
19 20
9 13
13 17
樣例輸出:
5
#include <iostream>
using namespace std;
int ss[1000 * 1000 + 2];
int num = 0;
void unions(int a, int b){
ss[a] = b;
}
int find(int a){
int k = a;
while(ss[k] > 0){
k = ss[k];
}
return k;
}
void f(int a, int b){
// cout << a << b << endl;
int c1 = find(a);
int c2 = find(b);
// cout << c1 << c2 << endl;
if(c1 == c2 && c1 != 0){
return ;
}
else{
unions(c1, c2);
num++;
}
}
int main(){
freopen("input.txt", "r", stdin);
int a, b, c;
cin >> a >> b >> c;
// cout << a << " " << b << " " << c << endl;
int d1, d2;
for(int i = 0; i < c; i++){
cin >> d1 >> d2;
// cout << d1 << " " << d2 << endl;
f(d1, d2);
}
// for(int i = 1; i < a * b; i++){
// cout << ss[i] << " ";
// if(i % 5 == 0){
// cout << endl;
// }
// }
// cout << a * b << endl;
// cout << num << endl;
cout << a * b - num;
}
6、最小生成樹(MST) Prim算法
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
int f(int n, int len[][102]){
int dis[102];
int visit[102];
memset(visit, 0, 102 * 4);
visit[1] = 1;
for (int i = 1; i <= 102; i++){
dis[i] = len[1][i];
}
int sum = 0;
for (int k = 2; k <= n; k++){
int min = 1 << 30;
int loc = 0;
for (int i = 2; i <= n; i++){
if (min > dis[i] && visit[i] == 0){
min = dis[i];
loc = i;
}
}
visit[loc] = 1;
cout << "loc" << loc << endl;
sum += min;
for(int i = 2; i <= n; i++){
if(visit[i] == 0 && dis[i] > len[loc][i]){
dis[i] = len[loc][i];
}
}
for(int i = 1; i <= n; i++){
cout << dis[i] << " " ;
}
cout << endl;
}
return sum;
}
int main(){
freopen("in.txt", "r", stdin);
int t;
int n, m;
int dis[102][102];
cin >> t;
for(int r = 0; r < t; r++){
cin >> n >> m;
int total = 0;
for (int i = 0; i < 102; i++){
for (int j = 0; j < 102; j++){
dis[i][j] = (1 << 30);
}
}
for (int i = 0; i <= 102; i++){
dis[i][i] = 0;
}
for (int j = 0; j < m; j++){
int a, b;
cin >> a >> b;
cin >> dis[a][b];
dis[b][a] = dis[a][b];
// cout << dis[a][b] << endl;
total += dis[a][b];
}
// cout << total << endl;
cout << total - f(n, dis) << endl;
}
}