記事のディレクトリ
質問は投稿されず、質問の考えとコードが記録されます。
詳細なトピックリンク
1.迷路(DFS)
問題解決のアイデア:
DFSは、各ポイントが順番に消えるかどうかを判断します。回答:31
コード
#include <iostream>
#include <cstring>
using namespace std;
const int N = 11;
int n = 10;
char g[N][N];
bool st[N][N];
int dx[4] = {
-1,0,1,0},dy[4] = {
0,1,0,-1};
int get(char c)
{
if(c == 'U') return 0;
else if(c == 'R') return 1;
else if(c == 'D') return 2;
else return 3;
}
bool dfs(int x,int y)
{
if(x <0 || x >= n || y < 0 || y >= n) return true;
st[x][y] = true;
int d = get(g[x][y]);
int a = x + dx[d], b = y + dy[d];
if(st[a][b]) return false;
if(dfs(a,b)) return true;
}
int main()
{
for(int i =0; i < n ;i ++ ) cin >> g[i];
int cnt = 0;
for(int i =0 ;i < n;i ++ )
for(int j = 0;j < n ; j ++ )
{
memset(st,0,sizeof st);
if(dfs(i,j)) cnt ++;
}
cout << cnt << endl;
}
// 答案:31
2.バッタジャンプ(BFS)
問題解決のアイデア:
回答:20
コード
#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
int get_0(string &s)
{
for(int i = 0; i < s.size();i ++ )
if(s[i] == '0') return i;
}
int bfs()
{
string start = "012345678";
string end = "087654321";
unordered_map<string,int> step;
int d[4] = {
1,2,-1,-2};
step[start] = 0;
queue<string> q;
q.push(start);
while(q.size())
{
string s = q.front();
q.pop();
int cnt = step[s];
if(s == end) return cnt;
int pos = get_0(s);
for(int i = 0;i < 4;i ++)
{
swap(s[pos],s[((pos + d[i]) % 9 + 9) % 9 ]) ;// C ++ 取模
if(step.count(s) == 0)
{
step[s] = cnt + 1;
q.push(s);
}
swap(s[pos],s[((pos + d[i]) % 9 + 9) % 9 ]) ;// 交换回来
}
}
}
int main()
{
cout << bfs() << endl;
return 0;
}
3.キューブステータス(BFS、いいえ)
問題解決のアイデア
他の大物へのリンクを添付、それもBFSのようです、トピックは参照するには難しすぎます
4.グリッド分割(DFS、いいえ)
問題解決のアイデア
5,6コードの空欄の質問(省略)
7.通常の問題(DFS)
問題解決のアイデア
再帰処理。dfsから返される()のxの数を考えましたが、それでも具体的な詳細を書くことができず、yの一般的な手法を学ぶ必要があります。
コード
#include <iostream>
using namespace std;
int k;
string s;
int dfs() // dfs返回一个()的x
{
int res = 0;
while(k < s.size())
{
if(s[k] == '(')
{
k ++; // 跳过 (
res += dfs();
k ++; // 跳过 )
}else if(s[k] == '|')
{
k ++ ; // 跳过 |
res = max(res,dfs());
}else if(s[k] == ')') break;
else if(s[k] == 'x')
{
k ++;
res ++;
}
}
return res;
}
int main()
{
cin >> s;
cout << dfs() << endl;
return 0;
}
8.パンの数を構成します(最大公約数+完全なバックパック)
問題解決のアイデア
すべての数の最大公約数dを見つけます.d!= 1の場合、使用できない数が無限にあることを示し、INFを出力します。
それ以外の場合は、完全なナップザックでそれを見つけ(n個のアイテムからk個の数字を選択、組み合わせ問題)、ボリュームの上限を10000と推測します。
定理:两个互斥的数p,q凑不到的最大整数:(p-1)*(q-1)-1
(購入できない質問の数に対応)
コード
#include <iostream>
using namespace std;
const int N = 10010;
int n;
bool f[110][N];
int a[110];
int gcd(int a,int b) // 求最大公因数
{
return b ? gcd(b,a % b) : a;
}
int main()
{
cin >> n;
int d = 0;
for(int i = 1;i <= n;i ++){
cin >> a[i];
d = gcd(d,a[i]);
}
if(d != 1) cout << "INF" << endl;
else
{
f[0][0] = true;
for(int i = 1;i <= n; i++)
for(int j = 0;j < N;j ++)
{
f[i][j] |= f[i-1][j];
if(j >= a[i]) f[i][j] |= f[i][j - a[i]]; // 完全背包
}
int res = 0;
for(int i = 0 ;i < N;i ++ ) {
if(!f[n][i])
res ++;
}
cout << res << endl;
}
return 0;
}
9.チョコレートを分ける(2点)
問題解決のアイデア
2点。最初に、最大の辺の長さが一致せず、それが答えの範囲内の二分法であると仮定します。時間計算量O(nlogn)
コード
#include <iostream>
using namespace std;
const int N = 100010;
int n,k;
int h[N],w[N];
bool check(int mid)
{
int sum = 0;
for(int i = 1;i <= n;i ++)
{
sum += (h[i] / mid) * (w[i] / mid);
}
return sum >= k;
}
int main()
{
cin >> n >> k;
int l = 1,r;
for(int i = 1;i <= n ;i ++)
{
cin >> h[i] >> w[i];
r = max(r,h[i]);
r = max(r,w[i]);
}
// 二分
while(l < r)
{
int mid = l + r + 1 >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
cout << r << endl;
return 0;
}
10.ペイント領域(線分ツリー、いいえ)
問題解決のアイデア
カバレッジがない場合は、2次元の差+プレフィックスの合計を使用できます。カバーされている、線分ツリーがわからない場合は、ポイントを欺くために激しく循環します。(ブール配列スペースを開くと小さくなります)
他の人の問題解決策