題目的意思很好理解找從最左邊到最右邊最短路(BFS)
#include <bits/stdc++.h>
using namespace std;
int a[510][510]; // 存儲網格中每個位置是否有障礙(1表示有障礙,0表示無障礙)
int v[510][510]; // 記錄每個位置是否被訪問過(1表示已訪問,0表示未訪問)
int ans, n, m; // ans: 最短路徑長度,n: 網格行數,m: 網格列數
queue<pair<int, int>> q; // 使用pair存儲坐標的隊列,用于BFS
int T; // 測試用例數量inline void solve(){// 初始化數組memset(a, 0, sizeof(a)); // 清空障礙物數組memset(v, 0, sizeof(v)); // 清空訪問標記數組cin >> n >> m; // 讀取網格行數和列數ans = n * m; // 初始化為最大可能值(網格總格子數)// 讀取每個行的障礙物信息for (int i = 1; i <= n; ++i) {int r, t;cin>>r; // 讀取第i行的障礙物數量for (int j = 1; j <= r; ++j) {cin>>t; // 讀取障礙物所在列a[i][t] = 1; // 標記該位置有障礙}}// 初始化BFS隊列:將所有第一列無障礙的位置加入隊列for (int i = 1; i <= n; ++i) {if (!a[i][1]) { // 如果該位置無障礙q.push({i, 1}); // 加入隊列v[i][1] = 1; // 標記為已訪問}}int t = 0; // 當前步數bool found = false; // 是否找到解的標志while (!q.empty() && !found) {t++; // 步數增加int s = q.size(); // 遍歷隊列里面的所有for (int j = 0; j < s; ++j) {auto [x, y] = q.front(); // 取出隊首坐標q.pop();// 如果到達最后一列,更新答案并結束搜索if (y == m) {ans = min(ans, t);found = true;break;}// 剪枝:如果當前步數加上剩余列數已經不可能更優,跳過,其實這里不用剪也行if (t + (m - y) >= ans) continue;// 嘗試向右移動if (y + 1 <= m && !v[x][y + 1] && !a[x][y + 1]) {v[x][y + 1] = 1;q.push({x, y + 1});}// 嘗試向下移動if (x + 1 <= n && !v[x + 1][y] && !a[x + 1][y]) {v[x + 1][y] = 1;q.push({x + 1, y});}// 嘗試向上移動if (x - 1 >= 1 && !v[x - 1][y] && !a[x - 1][y]) {v[x - 1][y] = 1;q.push({x - 1, y});}// 嘗試向左移動if (y - 1 >= 1 && !v[x][y - 1] && !a[x][y - 1]) {v[x][y - 1] = 1;q.push({x, y - 1});}}}cout << ans << endl; // 輸出當前測試用例的答案// 清空隊列,準備下一個測試用例while (!q.empty()) q.pop();
}
int main() {cin >> T; // 讀取測試用例數量while (T--) {solve();}return 0;
}
1007
其實這個題目不是很難,化簡后找相同的就可以,但是主要就是題目的判斷,一開始題目我讀錯了,導致看成是n1個開始節點,每次在前者的基礎上敲擊往后走,導致對題目的判斷出了差錯。。。。
本題稍微注意一點的就是要用雙指針來降復雜度,其他的沒啥(題目真的要先讀懂,不然都白費了)?
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline void solve(){int n1,n2;cin>>n1>>n2;vector<pair<int,int>>ni(n1),ca(n2);for(int i=0;i<n1;i++){cin>>ni[i].first>>ni[i].second;}for(int i=0;i<n2;i++){cin>>ca[i].first>>ca[i].second;}vector<int>a;vector<int>b;int sum=0;for(auto it:ni){int zong=(48*it.first)/it.second;//這里根據題目可以知道48是最大的公倍數,所以我們直接對它乘上a.push_back(sum);//sum就是在前者的基礎上加上現在的時刻sum+=zong;}sum=0;for(auto it:ca){int zong=(48*it.first)/it.second;b.push_back(sum);sum+=zong;}int count=0;/*for(int i=0;i<a.size();i++){cout<<a[i]<<" ";}cout<<endl;for(int j=0;j<b.size();j++){cout<<b[j]<<" ";}cout<<endl;*/int i=0,j=0;while(i<a.size()&&j<b.size()){//雙指針來進行判斷,因為a,b都是有序上升的if(a[i]==b[j]){count++;i++,j++;}else if(a[i]<b[j]){i++;}else{j++;}}cout<<count<<endl;
}
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n;cin>>n;while(n--)solve();
}