2012年
1.1322求子集重量之和
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
vector<int> v;
cin >> n;
int m = n;
while (m--)
{
int x;
cin >> x;
v.push_back(x);
}
int sum = 0;
for (int j = 0; j < n; j++)
{
bool i;
cin >> i;
if (i == 1)
{
sum += v[j];
}
}
cout << sum;
system("pause");
return 0;
}
2.1054字符串統計
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s;
getline(cin, s);
int alpha = 0, num = 0, blank = 0, others = 0;
for (auto i : s)
{
if (isdigit(i))
{
num++;
}
else if (isalpha(i))
{
alpha++;
}
else if (i == ' ')
{
blank++;
}
else
{
others++;
}
}
cout << alpha << " " << blank << " " << num << " " << others << endl;
system("pause");
return 0;
}
3.1082花生米系列
1.k任取
共有n粒,輸入n,甲先取k粒,乙再取k粒如此反覆,直到乙取走最後一粒。輸出k,若無解則輸出0.0<k<10、0<n<=1000
暴力法:k取值有10種,從k=9開始嘗試,成功就停止循環,不行k=8……都不行輸出0(事實上除了n=1之外都有解,我做的有錯嗎?)
兩人是否必須取滿k粒??此題擱置,在noj系統中提交時候再解
#include <bits/stdc++.h>
using namespace std;
bool isOk(int n, int k)
{
if (n <= k)
return 0;
if (n == 2)
{
cout << n << " 1" << endl;
return 1;
}
int quotient = n / k;
int remainder = n % k;
if (quotient % 2 == 0 and remainder == 0)
{
cout << n << " " << k << endl;
return 1;
}
return 0;
}
int main()
{
for (int j = 1; j < 1000; j++)
{
int flag = 1;
for (int i = 9; i > 0; i--)
{
if (isOk(j, i))
{
flag = 0;
break;
}
}
if (flag == 1)
cout << j << " 0" << endl;
}
system("pause");
return 0;
}
https://blog.csdn.net/qq_41727666/category_9279609.html
2.k=1或5或10
4.1091求解逆波蘭表達式
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s;
getline(cin, s);
stack<int> st;
int first, second;
for (auto i : s)
{
if (isdigit(i))
{
st.push(i - '0');
}
else
{
second = st.top();
st.pop();
first = st.top();
st.pop();
switch (i)
{
case '*':
st.push(first * second);
break;
case '/':
st.push(first / second);
break;
case '+':
st.push(first + second);
break;
case '-':
st.push(first - second);
break;
}
}
}
cout << st.top() << endl;
system("pause");
return 0;
}
5.1021柱狀圖
#include <bits/stdc++.h>
using namespace std;
int main()
{
map<char, int> mp;
for (int i = 0; i < 26; i++)
{
mp[char('A' + i)] = 0;
}
int max = -1;
char maxc;
for (int i = 0; i < 4; i++)
{
string s;
getline(cin, s);
for (auto i : s)
{
if (i >= 'A' and i <= 'Z')
{
mp[i]++;
if (mp[i] > max)
{
max = mp[i];
maxc = i;
}
}
}
}
char show[max + 1][26];
for (int i = 0; i < max + 1; i++)
{
for (int j = 0; j < 26; j++)
{
show[i][j] = ' ';
}
}
for (auto i : mp)
{
//cout << i.first << " " << i.second << endl;
for (int j = max; j > max - i.second; j--)
{
show[j][int(i.first - 'A')] = '*';
}
}
for (int i = 1; i < max + 1; i++)
{
for (int j = 0; j < 26; j++)
{
if (j == 0)
cout << show[i][j];
else
cout << " " << show[i][j];
}
cout << endl;
}
for (int i = 0; i < 25; i++)
{
cout << char(i + 'A') << " ";
}
cout << 'Z' << endl;
system("pause");
return 0;
}
6.1028判斷三角形
根據三角形“兩邊之和大於第三邊,兩邊之差小於第三邊”來判斷
7.1147木乃伊迷宮
沒做。挖坑。
8.數獨遊戲
數獨遊戲規則
在9階方陣中,包含了81個小格(九列九行),其中又再分成九個小正方形(稱爲宮),每宮有九小格。
遊戲剛開始時,盤面上有些小格已經填了數字(稱爲初盤),遊戲者要在空白的小格中填入1到9的數字,
使得最後每行、每列、每宮都不出現重複的數字,而且每一個遊戲都只有一個唯一的解答(稱爲終盤)。
輸入
一個9*9的矩陣,0表示該位置是空白。
輸出
一個9*9的矩陣,格式與輸入類似。
輸入樣例
900050060
020070100
300102040
703800529
000345000
516009403
050208006
007090010
030010004
輸出樣例
971453268
428976135
365182947
743861529
892345671
516729483
154238796
687594312
239617854
思路:DFS+剪枝,每個DFS函數處理一格子,不能填入的或全部填滿則函數終止,其他情況dfs函數處理下一格子。
#include <bits/stdc++.h>
using namespace std;
int b[9][9];
bool isValid(int x, int y, int num)
{
for (int i = 0; i < 9; i++)
{
if (b[i][y] == num)
return 0;
if (b[x][i] == num)
return 0;
}
int x0 = x / 3, y0 = y / 3;
for (int i = 3 * x0; i < 3 * x0 + 3; i++)
{
for (int j = 3 * y0; j < 3 * y0 + 3; j++)
{
if (b[i][j] == num)
return 0;
}
}
return 1;
}
void dfs(int row, int col)
{
if (row == 8 and col == 8)
{
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
cout << b[i][j];
}
cout << endl;
}
return;
}
if (b[row][col] != 0) //不能填入的 往前走一個格
{
if (col < 8)
{
dfs(row, col + 1);
}
else if (col == 8)
{
dfs(row + 1, 0);
}
}
else
{
bool flag = 1;
for (int n = 1; n <= 9; n++)
{
if (isValid(row, col, n))
{
b[row][col] = n;
flag = 0;
if (col < 8)
{
dfs(row, col + 1);
}
else if (col == 8)
{
dfs(row + 1, 0);
}
b[row][col] = 0; //撤銷掉 就像沒填過一樣
}
}
if (flag == 1) //一個都填不進去 返回
return;
}
}
int main()
{
for (int i = 0; i < 9; i++)
{
string s;
getline(cin, s);
for (int j = 0; j < 9; j++)
{
b[i][j] = s[j] - '0';
}
}
dfs(0, 0);
system("pause");
return 0;
}
2011年
1.斐波那契數列
#include <bits/stdc++.h>
using namespace std;
int dp[21];
void outPut(int n)
{
int flag = 1;
while (n >= 1)
{
for (int i = 20; i >= 1; i--)
{
if (n >= dp[i])
{
if (flag == 1)
{
cout << dp[i];
n -= dp[i];
flag = 0;
}
else
{
cout << "+" << dp[i];
n -= dp[i];
}
}
}
}
}
int main()
{
int n;
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i < 21; i++)
{
dp[i] = dp[i - 1] + dp[i - 2];
//cout << i << " " << dp[i] << endl;
}
while (cin >> n && n != 0)
{
cout << n << "=";
outPut(n);
cout << endl;
}
system("pause");
return 0;
}
2.打印楊輝三角
注意memset函數用法int b[K][2 * K - 1]; memset(b, 0, sizeof(b));
#include <bits/stdc++.h>
using namespace std;
int main()
{
int K;
cin >> K;
int b[K][2 * K - 1];
memset(b, 0, sizeof(b));
b[0][K - 1] = 1;
for (int i = 0; i < 2 * K - 1; i++)
{
if (b[0][i] == 0)
{
cout << " " << " ";
}else{
cout<<b[0][i]<<" ";
}
}
cout << endl;
for (int i = 1; i < K; i++)
{
for (int j = 0; j < 2 * K - 1; j++)
{
if (j - 1 >= 0 and j + 1 < 2 * K - 1)
{
b[i][j] = b[i - 1][j - 1] + b[i - 1][j + 1];
}
if (i + j == K - 1 or j - i == K - 1)
{
b[i][j] = 1;
}
if (b[i][j] == 0)
{
cout << " " << " ";
}else{
cout<<b[i][j]<<" ";
}
}
cout << endl;
}
system("pause");
return 0;
}
3.調整N階方陣的主元@@@
#include <bits/stdc++.h>
using namespace std;
ostream &operator<<(ostream &out, const vector<vector<int>> v)
{
for (int i = 0; i < v.size(); i++)
{
for (int j = 0; j < v.size(); j++)
{
out << v[i][j] << " ";
}
out << endl;
}
return out;
}
void transfer(vector<vector<int>> &v)
{
for (int t = 0; t < v.size(); t++)
{
int max = -1, flag;
for (int i = t; i < v.size(); i++)
{
if (v[i][0] > max)
{
max = v[i][0];
flag = i;
}
swap(v[t], v[flag]);
}
}
}
int main()
{
ifstream inf; //infile
inf.open(R"(H:\matrix.txt)");
if (!inf.is_open())
{
cout << "cant open file.";
return -1;
}
while (inf.good())
{
int N;
inf >> N;
if (N == 0)
break;
vector<vector<int>> v(N, vector<int>(N, 0));
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
int x;
inf >> x;
v[i][j] = x;
}
}
transfer(v);
cout << v << endl;
}
inf.close();
system("pause");
return 0;
}
matrix.txt文件內容爲:
4
1 2 3 4
5 6 7 8
2 3 4 5
1 3 4 6
8
12 23 43 12 23 45 64 61
34 54 12 34 89 16 40 34
34 54 12 54 71 12 65 34
54 32 66 54 51 47 16 73
26 34 63 14 65 35 76 23
12 45 63 73 62 56 76 15
67 23 90 89 73 71 81 21
12 56 80 91 33 54 12 56
2
1 2
2 1
1
1
0
4.合併字符串
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s1, s2;
getline(cin, s1);
getline(cin, s2);
string s = "";
reverse(s2.begin(), s2.end());
if (s1.size() >= s2.size())
{
for (int i = 0; i < s1.size(); i++)
{
if (i < s2.size())
{
s += s1[i];
s += s2[i];
}
else
{
s += s1[i];
}
}
}
else
{
for (int i = 0; i < s2.size(); i++)
{
if (i < s1.size())
{
s += s1[i];
s += s2[i];
}
else
{
s += s2[i];
}
}
}
cout << s << endl;
system("pause");
return 0;
}
5.多項式加法
#include <bits/stdc++.h>
using namespace std;
int main()
{
ifstream inf;
inf.open(R"(H:\polyn.txt)");
if (!inf.is_open())
{
cout << "can not open.";
}
while (1)
{
map<int, int, greater<int>> mp;
mp.erase(mp.begin(), mp.end());
int n1, n2;
inf >> n1;
for (int i = 0; i < n1; i++)
{
int a, b;
inf >> a >> b;
mp[b] += a;
}
inf >> n2;
for (int i = 0; i < n2; i++)
{
int a, b;
inf >> a >> b;
mp[b] += a;
}
if (n1 == 0 and n2 == 0)
break;
for (auto i : mp)
{
cout << i.second << " " << i.first << " ";
}
cout<<endl;
}
system("pause");
return 0;
}
polyn.txt:
3 3 5 -2 1 4 0
4 2 3 -1 2 1 1 3 0
3 1 2 1 1 1 0
3 2 2 2 1 2 0
0
0
2010年
1.1041.最長公共子序列(DP)@@@
學習https://blog.csdn.net/bitcarmanlee/article/details/88977705
- 定義狀態:
DP[i][j]表示,串1以第i個字符結尾、串2以第j個字符結尾時,他們的最長公共子序列。例如asdf和aspq,DP[1][1]=1、DP[1][2]=1、DP[2][2]=2 - 定義狀態轉移方程
代碼非常好寫,主要是上面的狀態方程得弄清楚了
#include <bits/stdc++.h>
using namespace std;
int main()
{
while (1)
{
string s1, s2;
getline(cin, s1, ' ');
getline(cin, s2);
if (s1.size() == 0 or s2.size() == 0)
break;//本題沒說退出條件是怎樣的
s1.insert(s1.begin(), 'x');
s2.insert(s2.begin(), 'x');//填充無用字符
int dp[s1.size()][s2.size()];
for (int i = 0; i < s1.size(); i++)
{
for (int j = 0; j < s2.size(); j++)
{
if (i == 0 or j == 0)
dp[i][j] = 0;
else
{
if (s1[i] == s2[j])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else
{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
}
cout << dp[s1.size() - 1][s2.size() - 1] << endl;
}
system("pause");
return 0;
}
再來看看最長公共子串的情況,也就是說字符串必須連續的情況,只需要改變狀態轉移方程即可:
#include <bits/stdc++.h>
using namespace std;
int main()
{
while (1)
{
string s1, s2;
int max = -1;
getline(cin, s1, ' ');
getline(cin, s2);
if (s1.size() == 0 or s2.size() == 0)
break; //本題沒說退出條件是怎樣的
s1.insert(s1.begin(), 'x');
s2.insert(s2.begin(), 'x'); //填充無用字符
int dp[s1.size()][s2.size()];
for (int i = 0; i < s1.size(); i++)
{
for (int j = 0; j < s2.size(); j++)
{
if (i == 0 or j == 0)
dp[i][j] = 0;
else
{
if (s1[i] == s2[j])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else
{
dp[i][j] = 0;
}
}
dp[i][j] > max ? max = dp[i][j] : NULL;
}
}
cout << max << endl;
}
system("pause");
return 0;
}
2.1144農場灌溉問題(DFS)@@@
首先我的思路是深搜,看了眼1441連陰雨這道題的解法,發現其實是同一題:
- 標記數組用來存每個格子的髒位
- 對每個格子用dfs函數,儘可能地標記附近的格子,即水流能流到的格子(深搜)
- 遍歷每個格子
- 如果未被標記,調用bfs,計數器加1,因爲附近的格子的水沒流到此格子
- 如果被標記,說明附近格子的水流到此格子,計數器不用加,此格子直接略過不調用bfs函數
- 遍歷完畢了,計數器的值就是離散水坑的值。
如果我還沒說明白,舉個例子:地圖上所有點都連在了一起(水流覆蓋全圖),bfs第一個點時,其他所有點都會被標記,主函數裏計數器值等於1。此時繼續遍歷其他點,發現被標記什麼也不做,那麼計數器值不變還是1。說明全圖只有一個水坑。
#include <bits/stdc++.h>
using namespace std;
unordered_map<char, array<bool, 4>> mp; //上下左右可前進表
void dfs(int x, int y, vector<vector<char>> &b, vector<vector<bool>> &mark)
{
mark[x][y] = 1;
int m = b.size();
int n = b[0].size();
if (mp[b[x][y]][0] == 1 and (x - 1) >= 0 and mp[b[x - 1][y]][1] == 1 and mark[x - 1][y] == 0)
dfs(x - 1, y, b, mark);
if (mp[b[x][y]][1] == 1 and (x + 1) < m and mp[b[x + 1][y]][0] == 1 and mark[x + 1][y] == 0)
dfs(x + 1, y, b, mark);
if (mp[b[x][y]][2] == 1 and (y - 1) >= 0 and mp[b[x][y - 1]][3] == 1 and mark[x][y - 1] == 0)
dfs(x, y - 1, b, mark);
if (mp[b[x][y]][3] == 1 and (y + 1) < n and mp[b[x][y + 1]][2] == 1 and mark[x][y + 1] == 0)
dfs(x, y + 1, b, mark);
}
int main()
{
//誰能告訴我更簡單的插入方法?
mp.insert({'A', {1, 0, 1, 0}});
mp.insert({'B', {1, 0, 0, 1}});
mp.insert({'C', {0, 1, 1, 0}});
mp.insert({'D', {0, 1, 0, 1}});
mp.insert({'E', {1, 1, 0, 0}});
mp.insert({'F', {0, 0, 1, 1}});
mp.insert({'G', {1, 0, 1, 1}});
mp.insert({'H', {1, 1, 1, 0}});
mp.insert({'I', {0, 1, 1, 1}});
mp.insert({'J', {1, 1, 0, 1}});
mp.insert({'K', {1, 1, 1, 1}});
while (1)
{
int m, n;
cin >> m >> n;
if (m == -1 and n == -1)
break;
cin.get();//喫空格
vector<vector<char>> b(m, vector<char>(n, '?')); //棋盤
vector<vector<bool>> mark(m, vector<bool>(n, 0)); //標記
for (int i = 0; i < m; i++)
{
string s;
getline(cin, s, ' ');
for (int j = 0; j < s.size(); j++)
{
b[i][j] = s[j];
}
}
int count = 0;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (mark[i][j] == 1)
continue; //如果點都標記過 count不用加
dfs(i, j, b, mark); //標記儘可能走到的點
count++;
}
}
cout << count << " ";
}
cout<<endl;
system("pause");
return 0;
}
總結,這是一個dfs經典題,需要多鑽研。
3.迴文質數
因爲151既是一個質數又是一個迴文數(從左到右和從右到左是看一樣的),所以 151 是迴文質數。
寫一個程序來找出範圍[a,b](5 <= a < b <= 100,000,000)( 一億)間的所有迴文質數;
Input:
多組輸入數據
第 1 行: 二個整數 a 和 b .
Output:
輸出一個迴文質數的列表,一行一個。
Sample Input:
5 500
Sample Output:
5
7
11
101
131
151
181
191
313
353
373
383
注意判斷質數的方法!
#include <bits/stdc++.h>
using namespace std;
bool is_prime(long x)
{
int k = sqrt(x);
for (int i = 2; i <= k; i++)
{
if (x % i == 0)
return 0;
}
return 1;
}
bool is_huiwen(long x)
{
string s = "";
while (x)
{
s += x % 10 + '0';
x /= 10;
}
string ss = s;
reverse(s.begin(), s.end());
return s == ss;
}
int main()
{
long a, b;
cin >> a >> b;
for (int i = a; i <= b; i++)
{
if (is_huiwen(i) and is_prime(i))
{
cout << i << endl;
}
}
system("pause");
return 0;
}
接下來我想測試下,是先判斷迴文數還是先判斷質數,程序會快一定,我把main函數改了
int main()
{
clock_t start = clock();
int a = 5, b = 10000000;
int count = 0;
for (int i = a; i <= b; i++)
{
if (is_prime(i) and is_huiwen(i))
{
//衆所周知,is_prime函數返回0後,is_huiwen函數將不會執行
count++;//無意義語句
}
}
clock_t finish = clock();
cout << "time consming:" << finish - start << endl;
system("pause");
return 0;
}
多次運算取平均值:先判斷質數時,輸出6947,先判斷迴文數時,輸出7951。多了1000個cpu時鐘週期。
clock()是C/C++中的計時函數,而與其相關的數據類型是clock_t。
它的具體功能是返回處理器調用某個進程或函數所花費的時間。函數返回從“開啓這個程序進程”到“程序中調用clock()函數”時之間的CPU時鐘計時單元(clock tick)數
我的cpu主頻是2.5GHz,1000個時鐘週期是400ns=0.4us,影響不大,但是說明先判斷質數會快一點,可能因爲isprime函數返回0要多一些,即非質數多於非迴文數。
4.1005裝載問題??
參考這裏
描述
有兩艘船,載重量分別是c1、 c2,n個集裝箱,重量是wi (i=1…n),且所有集裝箱的總重量不超過c1+c2。確定是否有可能將所有集裝箱全部裝入兩艘船。
輸入
多個測例,每個測例的輸入佔兩行。第一行一次是c1、c2和n(n<=10);第二行n個整數表示wi (i=1…n)。n等於0標誌輸入結束。
輸出
對於每個測例在單獨的一行內輸出Yes或No。
輸入樣例
7 8 2
8 7
7 9 2
8 8
0 0 0
輸出樣例
Yes
No
提示
求出不超過c1的最大值max,若總重量-max < c2則能裝入到兩艘船。
#include <stdio.h>
int c1, c2, n;
int w[11];
int cw, bestw, r;
void backtack(int i)
{
if (i > n)
{
if (cw > bestw)
{
bestw = cw;
}
return;
}
r -= w[i];
if (cw + w[i] <= c1)
{
cw += w[i];
backtack(i + 1);
cw -= w[i];
}
if (cw + r > bestw)
{
backtack(i + 1);
}
r += w[i];
}
int main()
{
while (scanf("%d%d%d", &c1, &c2, &n) != 0 && n != 0)
{
cw = 0, bestw = 0, r = 0;
int i;
for (i = 1; i <= n; i++)
{
scanf("%d", &w[i]);
r += w[i];
}
backtack(1);
if (r - bestw <= c2)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
2009年
1 .奶牛飛盤隊??
- 題意:有N(1≤N≤2000)只奶牛,每隻奶牛都有一個指數R(1≤R≤100000),請你在這N頭牛中選出多於1只牛,使指數之和是一個數F的倍數。求出有多少種方式,結果mod1億
- 錯解:0/1揹包變形,求種數
- 正解:標準經典動歸,與有道難題火柴遊戲類似,都需要用到mod,因爲要求出組成的f的倍數,所以方程爲f[i][j]:=f[i-1][j]+f[i-1][j+l-(a[i] mod l)) mod l]);要善用mod湊餘數的思想,減少複雜度。初值要注意f[0][0]:=1;最後結果f[n][0]-1
不會,挖坑
2.約瑟夫問題@@
約瑟夫問題是一個非常經典的題
我專門寫了篇博客,點我傳送過去
3.N皇后問題
DFS+剪枝(填表時要回溯)。
輸入N,表示N*N棋盤,輸出不同解的個數。(輸入4得2,輸入8得92)
#include <bits/stdc++.h>
using namespace std;
int cnt = 0;
void outPut(const vector<vector<char>> &b)
{
for (int i = 0; i < b.size(); i++)
{
for (int j = 0; j < b.size(); j++)
{
cout << b[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
void mark(int x, int y, vector<vector<char>> &b)
{
int n = b.size();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
b[x][j] = '+';
b[i][y] = '+';
if (i + j == x + y or i - j == x - y)
{
b[i][j] = '+';
}
}
}
b[x][y] = 'x';
//outPut(b);
}
void dfs(int level, vector<vector<char>> &b)
{
if (level == b.size())
{
//outPut(b);
cnt++;
return;
}
for (int i = 0; i < b.size(); i++)
{
if (b[level][i] == '.')
{
vector<vector<char>> tmp = b;
mark(level, i, b);
dfs(level + 1, b);
b = tmp;
//outPut(b);
}
}
}
int main()
{
int N;
cin >> N;
vector<vector<char>> b(N, vector<char>(N, '.')); //棋盤
dfs(0, b);
cout << cnt << endl;
system("pause");
}
下面兩題不做:
- 給4個座標判正方形:先找出兩橫看是否平行,再找出兩豎看是否平行,如此就判斷完是不是四邊形。再計算邊長是否相等即可
- 合併有序數組:可以把兩個數組直接放在一個數組裏排序,或者雙指針,按序插入新數組
4.求圖像的周長DFS@@
我突然找到一個網站。。可以刷nwpu的題,可能是acm隊的
我一開始做錯了,後來發現X周圍非X的點代表着一單位的長度不需要額外記錄,就做出來了。debug花了好久,主要是int n = b.size(); int m = b[0].size();
把mn搞混了,然後走方向時候手寫8個方向而不是for循環,寫錯了一個導致全錯。走方向如果不用for循環,發生錯誤的概論是for循環的8倍。
最後感覺腦子不靈活,可能做了一天了,腦子有點懶。
#include <bits/stdc++.h>
using namespace std;
int sum;
int count(int x, int y, vector<vector<char>> &b)
{
int cnt = 0;
int n = b.size();
int m = b[0].size();
if (x - 1 < 0)
cnt++;
if (x + 1 >= n)
cnt++;
if (y - 1 < 0)
cnt++;
if (y + 1 >= m)
cnt++;
if (x - 1 >= 0 and b[x - 1][y] == '.')
cnt++;
if (x + 1 < n and b[x + 1][y] == '.')
cnt++;
if (y - 1 >= 0 and b[x][y - 1] == '.')
cnt++;
if (y + 1 < m and b[x][y + 1] == '.')
cnt++;
return cnt;
}
bool isValid(int x, int y, vector<vector<char>> &b, vector<vector<bool>> &mp)
{
int m = b.size();
int n = b[0].size();
if (x < m and x >= 0 and y < n and y >= 0 and b[x][y] == 'X' and mp[x][y] == 0)
return 1;
return 0;
}
void dfs(int x, int y, vector<vector<char>> &b, vector<vector<bool>> &mp)
{
mp[x][y] = 1;
sum += count(x, y, b);
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (i == 0 and j == 0)
continue;
int xx = x + i;
int yy = y + j;
if (isValid(xx, yy, b, mp))
{
dfs(xx, yy, b, mp);
}
}
}
}
int main()
{
while (1)
{
int m, n, x, y;
cin >> m >> n >> x >> y;
if (m == 0 and n == 0 and x == 0 and y == 0)
break;
cin.get(); //喫y後面那個空格 不然s輸不進去
vector<vector<char>> b(m, vector<char>(n, '?'));
vector<vector<bool>> mp(m, vector<bool>(n, 0));
for (int i = 0; i < m; i++)
{
string s;
getline(cin, s, ' ');
for (int j = 0; j < n; j++)
{
b[i][j] = s[j];
}
}
dfs(x - 1, y - 1, b, mp);
cout << sum << endl;
sum = 0;
}
system("pause");
}
測試用例2 2 2 2 XX XX 2 2 2 1 .X X. 6 4 2 3 .XXX .XXX .XXX ...X ..X. X... 0 0 0 0
2008年
1.越野跑
#include <bits/stdc++.h>
using namespace std;
int main()
{
int time = 0;
int M, T, U, F, D;
cin >> M >> T >> U >> F >> D;
int duan = 0;
for (int i = 0; i < T; i++)
{
char c;
cin >> c;
switch (c)
{
case 'u':
case 'd':
time += (U + D);
break;
case 'f':
time += (2 * F);
break;
default:
break;
}
if (time > M)
{
duan = i;
break;
}
}
cout << duan << endl;
system("pause");
}
2.環形石子合併DP
1、問題描述:問題來源 NWPU noj 1148
在一個圓形操場的四周擺放着n堆石子(n<= 100),現要將石子有次序地合併成一堆。規定每次只能選取相鄰的兩堆合併成新的一堆,並將新的一堆的石子數,記爲該次合併的得分。編一程序,讀入石子堆數n及每堆的石子數(<=20)。選擇一種合併石子的方案,使得做n-1次合併,得分的總和最小; 比如有4堆石子:44 5 9 則最佳合併方案如下:
4 4 5 9 score: 0
8 5 9 score: 8
13 9 score: 8 + 13 = 21
22 score: 8 + 13 + 22 = 43
2、輸入
可能有多組測試數據。 當輸入n=0時結束! 第一行爲石子堆數n(1<=n<=100);第二行爲n堆的石子每堆的石子數,每兩個數之間用一個空格分隔。
3、輸出
合併的最小得分,每個結果一行。
4、問題解析
這個問題和直線型的區別在於最後一堆和第一堆也是相鄰的,可以把圓形轉換成直線型,把問題擴展爲2n-1堆石子,舉個例子,如果環形石子堆是4 4 5 9,那麼轉換成直線型就變成了 4 4 5 9 4 4 5,所以最終就不是計算 0~n-1了,而是在 0n-1,1-n,2-n+1,…,n-12n-2中選擇最小的。計算方法和直線型的相同。
#include <bits/stdc++.h>
using namespace std;
int sum(int i, int j, vector<int> b)
{
int ret = 0;
for (int t = i; t <= j; t++)
{
ret += b[t];
}
return ret;
}
int fun(vector<int> &b)
{
int ret = INT8_MAX;
int size = b.size();
int size0 = (size + 1) / 2;
vector<vector<int>> dp(size, vector<int>(size, 0));
for (int s = 1; s < size0; s++) //step步數差異
{
for (int i = 0; i < size - 1; i++)
{
for (int j = i + 1; j < size; j++)
{
if (j - i == s)
{
if (s == 1)
dp[i][j] = b[i] + b[j];
else
{
int min = INT8_MAX;
for (int step = i; step < j; step++)
{
int tmp = dp[i][step] + dp[step + 1][j];
tmp < min ? min = tmp : NULL;
}
dp[i][j] = min + sum(i, j, b);
}
if (s == size0 - 1)
{
ret > dp[i][j] ? ret = dp[i][j] : NULL;
}
}
}
}
}
return ret;
}
int main()
{
while (1)
{
int n;
cin >> n;
if (n == 0)
break;
vector<int> b(0);
for (int i = 0; i < n; i++)
{
int num;
cin >> num;
b.push_back(num);
}
//擴充數組b
int size0 = b.size();
for (int i = 0; i < size0 - 1; i++)
{
b.push_back(b[i]);
}
cout << fun(b) << endl;
}
system("pause");
}
與其他人的答案對比過,輸出一樣,程序正確。