[ブルーブリッジカップ]第8回ブルーブリッジカップ(2017)-州大会の問題解決_C / C ++ __大学グループA

質問は投稿されず、質問の考えとコードが記録されます。

詳細なトピックリンク

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次元の差+プレフィックスの合計を使用できます。カバーされている、線分ツリーがわからない場合は、ポイントを欺くために激しく循環します。(ブール配列スペースを開くと小さくなります)
他の人の問題解決策

おすすめ

転載: blog.csdn.net/weixin_43154149/article/details/109036812