AtCoder題解 —— AtCoder Beginner Contest 183 —— C - Travel
題目相關
題目連結
AtCoder Beginner Contest 183 C 題,https://atcoder.jp/contests/abc183/tasks/abc183_c。
Problem Statement
There are N cities. The time it takes to travel from City i to City j is Ti,j.
Among those paths that start at City 1, visit all other cities exactly once, and then go back to City 1, how many paths take the total time of exactly K to travel along?
Input
Input is given from Standard Input in the following format:
N K
T1,1 ... T1,N
.
.
TN,1 ... TN,N
Output
Print the answer as an integer.
Samples1
Sample Input 1
4 330
0 1 10 100
1 0 20 200
10 20 0 300
100 200 300 0
Sample Output 1
2
Explaination
There are six paths that start at City 1, visit all other cities exactly once, and then go back to City 1:
- 1→2→3→4→1
- 1→2→4→3→1
- 1→3→2→4→1
- 1→3→4→2→1
- 1→4→2→3→1
- 1→4→3→2→1
The times it takes to travel along these paths are 421, 511, 330, 511, 330, and 421, respectively, among which two are exactly 330.
Samples2
Sample Input 2
5 5
0 1 1 1 1
1 0 1 1 1
1 1 0 1 1
1 1 1 0 1
1 1 1 1 0
Sample Output 2
24
Explaination
In whatever order we visit the cities, it will take the total time of 5 to travel.
Constraints
- 2≤N≤8
- If i≠j, 1≤Ti,j≤10^8.
- Ti,i=0
- Ti,j=Tj,i
- 1≤K≤10^9
- All values in input are integers.
題解報告
題目翻譯
有 N 個城市,從城市 i 到城市 j 需要的時間記為 Ti,j。問從城市 1 出發,經過所有的其他城市,再回到城市 1,而且每個城市只能走一次。求需要時間正好為 K 的線路個數。
樣例資料分析
這個題目樣例i資料解釋中已經說明的非常詳細,我們不需要分析樣例資料。
題目分析
根據樣例資料 1,一共有 4 個城市,我們知道從城市 1 出發遍歷所有城市,這就是一個全排列問題。使用模擬演算法,基本思路就是,寫出所有從 1 出發的全排列,然後計算出這個路線需要的時間,如果和 K 相同,我們就找到了一個答案。
考慮到本題的資料 N 最大為 8。因此 8 個城市,從 1 出發的全排列為 7!=5040,也就是說模擬演算法是可以在規定的時間內完成的。這樣本問題就轉換為如何寫出全排列。
使用 C++ STL 寫出全排列是一個非常容易的事情。我們可以使用 algrothim 庫中的 next_permutation() 函式即可完成這個任務。
AC 參考程式碼
//https://atcoder.jp/contests/abc183/tasks/abc183_c
//C - Travel
#include <bits/stdc++.h>
using namespace std;
const int MAXN=10;
int nums[MAXN][MAXN];
int main() {
int n,k;
cin>>n>>k;
int i;
for (i=1; i<=n; i++) {
for (int j=1; j<=n; j++) {
cin>>nums[i][j];
}
}
vector<int> idx(n+2);
iota(idx.begin(), idx.end(), 0);
idx[n+1]=1;
int ans=0;
do {
int sum=0;
for (i=2; i<=n+1; i++) {
sum+=nums[idx[i-1]][idx[i]];
}
if (sum==k) {
ans++;
}
} while (next_permutation(idx.begin()+2, idx.end()-1));
cout<<ans<<"\n";
return 0;
}
時間複雜度
O(N^2)。主要的時間消耗在讀取資料上。
空間複雜度
O(N^2)。
問題擴充套件
當 N 持續擴大。比如 N 變成 11,這樣 10!=3.7e6,繼續使用模擬演算法,就不一定能通過了。該如何改進演算法?我去,我一下也沒想明白。鴿一下。
相關文章
- AtCoder Beginner Contest 183 總結
- AtCoder Beginner Contest 352題解
- AtCoder Beginner Contest 378 題解
- 題解:AtCoder Beginner Contest 367
- AtCoder Beginner Contest 381 題解
- 題解:AtCoder Beginner Contest 371
- AtCoder Beginner Contest 376 題解
- AtCoder Beginner Contest 350 A - G 題解
- AtCoder Beginner Contest 380 (A~E)題解
- AtCoder Beginner Contest 238 A - F 題解
- AtCoder Beginner Contest 345 A-F 題解
- Atcoder Beginner Contest 380 題解 (A-G)
- Atcoder Beginner Contest 356題解(D、E)
- AtCoder Beginner Contest 353 (補題)
- KEYENCE Programming Contest 2024(AtCoder Beginner Contest 374)題解
- AtCoder Beginner Contest 350
- AtCoder Beginner Contest 349
- AtCoder Beginner Contest 347
- AtCoder Beginner Contest 343
- AtCoder Beginner Contest 344
- AtCoder Beginner Contest 346
- AtCoder Beginner Contest 353
- AtCoder Beginner Contest 354
- AtCoder Beginner Contest 352
- AtCoder Beginner Contest 351
- 【AtCoder Beginner Contest 347】
- AtCoder Beginner Contest 348
- AtCoder Beginner Contest 204
- AtCoder Beginner Contest 345
- AtCoder Beginner Contest 355
- AtCoder Beginner Contest 382
- AtCoder Beginner Contest 376
- AtCoder Beginner Contest 373
- AtCoder Beginner Contest 374
- AtCoder Beginner Contest 379
- AtCoder Beginner Contest 380
- AtCoder Beginner Contest 381
- AtCoder Beginner Contest 372