제출 #1180208

#제출 시각아이디문제언어결과실행 시간메모리
1180208ericl23302Skyscraper (JOI16_skyscraper)C++20
15 / 100
2 ms1608 KiB
#include <iostream> #include <vector> #include <algorithm> #include <cstdlib> #include <map> #define int long long using namespace std; // int code(int n, int l, vector<int> &heights) { // sort(heights.begin(), heights.end()); // heights.push_back(1001); // vector<vector<vector<vector<int>>>> dp(n + 1, vector<vector<vector<int>>>(n + 1, vector<vector<int>>(l + 1, vector<int>(3, 0)))); // dp[0][0][0][0] = 1; // for (int i = 1; i <= n; ++i) { // for (int j = 1; j <= i; ++j) { // for (int k = 0; k <= l; ++k) { // for (int e = 0; e < 3; ++e) { // // cout << i << ' ' << j << ' ' << k << ' ' << e << '\n'; // if (i + j - e > n || k < (2 * j - e) * (heights[i] - heights[i - 1]) || (i < n && j == 1 && e == 2)) continue; // // cout << "if\n"; // int newTot = k - (2 * j - e) * (heights[i] - heights[i - 1]); // // case 1: adding new building as new segment not at edge // dp[i][j][k][e] += dp[i - 1][j - 1][newTot][e]; // // cout << "case 1\n"; // // case 2: adding new building as new segment at edge // if (e) dp[i][j][k][e] += (3 - e) * dp[i - 1][j - 1][newTot][e - 1]; // // cout << "case 2\n"; // // case 3: adding new building onto segment, not merging segments, not onto edge // dp[i][j][k][e] += (2 * j - e) * dp[i - 1][j][newTot][e]; // // cout << "case 3\n"; // // case 4: adding new building onto segment, at edge // if (e == 1) dp[i][j][k][e] += 2 * j * dp[i - 1][j][newTot][e - 1]; // else if (e == 2) { // if (j == 1) dp[i][j][k][e] += dp[i - 1][j][newTot][e - 1]; // else dp[i][j][k][e] += (j - 1) * dp[i - 1][j][newTot][e - 1]; // } // // cout << "case 4\n"; // // case 5: adding new building onto segment, merging two // if (e == 0) dp[i][j][k][e] += j * (j + 1) * dp[i - 1][j + 1][newTot][e]; // else if (e == 1) dp[i][j][k][e] += j * j * dp[i - 1][j + 1][newTot][e]; // else if (j == 1) dp[i][j][k][e] += dp[i - 1][j + 1][newTot][e]; // else dp[i][j][k][e] += j * (j - 1) * dp[i - 1][j + 1][newTot][e]; // // cout << "case 5\n"; // dp[i][j][k][e] %= 1'000'000'007; // // cout << i << ' ' << j << ' ' << k << ' ' << e << ' ' << dp[i][j][k][e] << '\n'; // } // } // } // } // int res = 0; // for (int i = 0; i <= l; ++i) { // res += dp[n][1][i][2]; // res %= 1'000'000'007; // } // heights.pop_back(); // return res; // } // int bruteforce(int n, int l, vector<int> &heights) { // sort(heights.begin(), heights.end()); // int res = 0; // do { // int cur = 0; // for (int i = 0; i < n - 1; ++i) cur += abs(heights[i] - heights[i + 1]); // res += (cur <= l); // } while (next_permutation(heights.begin(), heights.end())); // return res; // } signed main() { ios_base::sync_with_stdio(0); cin.tie(0); int n, l; cin >> n >> l; vector<int> heights(n); for (int &i : heights) cin >> i; sort(heights.begin(), heights.end()); heights.push_back(1001); vector<vector<vector<vector<int>>>> dp(n + 1, vector<vector<vector<int>>>(n + 1, vector<vector<int>>(l + 1, vector<int>(3, 0)))); dp[0][0][0][0] = 1; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= i; ++j) { for (int k = 0; k <= l; ++k) { for (int e = 0; e < 3; ++e) { // cout << i << ' ' << j << ' ' << k << ' ' << e << '\n'; if (i + j - e > n || k < (2 * j - e) * (heights[i] - heights[i - 1]) || (i < n && j == 1 && e == 2)) continue; // cout << "if\n"; int newTot = k - (2 * j - e) * (heights[i] - heights[i - 1]); // case 1: adding new building as new segment not at edge dp[i][j][k][e] += dp[i - 1][j - 1][newTot][e]; // cout << "case 1\n"; // case 2: adding new building as new segment at edge if (e) dp[i][j][k][e] += (3 - e) * dp[i - 1][j - 1][newTot][e - 1]; // cout << "case 2\n"; // case 3: adding new building onto segment, not merging segments, not onto edge dp[i][j][k][e] += (2 * j - e) * dp[i - 1][j][newTot][e]; // cout << "case 3\n"; // case 4: adding new building onto segment, at edge if (e == 1) dp[i][j][k][e] += 2 * j * dp[i - 1][j][newTot][e - 1]; else if (e == 2) { if (j == 1) dp[i][j][k][e] += dp[i - 1][j][newTot][e - 1]; else dp[i][j][k][e] += (j - 1) * dp[i - 1][j][newTot][e - 1]; } // cout << "case 4\n"; // case 5: adding new building onto segment, merging two if (e == 0) dp[i][j][k][e] += j * (j + 1) * dp[i - 1][j + 1][newTot][e]; else if (e == 1) dp[i][j][k][e] += j * j * dp[i - 1][j + 1][newTot][e]; else if (j == 1) dp[i][j][k][e] += dp[i - 1][j + 1][newTot][e]; else dp[i][j][k][e] += j * (j - 1) * dp[i - 1][j + 1][newTot][e]; // cout << "case 5\n"; dp[i][j][k][e] %= 1'000'000'007; // cout << i << ' ' << j << ' ' << k << ' ' << e << ' ' << dp[i][j][k][e] << '\n'; } } } } int res = 0; for (int i = 0; i <= l; ++i) { res += dp[n][1][i][2]; res %= 1'000'000'007; } cout << res << '\n'; // srand(time({})); // int n = 8; // for (int i = 0; i < 100; ++i) { // vector<int> heights; // vector<bool> inHeights(1001, false); // while (heights.size() < n) { // int val = rand() % 20 + 1; // if (inHeights[val]) continue; // inHeights[val] = true; // heights.push_back(val); // } // sort(heights.begin(), heights.end()); // cout << "Test " << i + 1 << ": \n"; // for (int &j : heights) cout << j << ' '; // cout << '\n'; // for (int l = 0; l <= 100; l += rand() % 10 + 1) { // cout << "l: " << l << '\n'; // int codeVal = code(n, l, heights); // cout << "CodeVal: " << codeVal << '\n'; // int bruteforceVal = bruteforce(n, l, heights); // cout << "BruteforceVal: " << bruteforceVal << '\n'; // if (codeVal != bruteforceVal) { // cout << "Error\n"; // return 0; // } // } // } // vector<int> heights = {6, 7, 8, 9}; // cout << code(4, 4, heights) << '\n'; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...