日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2022CCSP T1最少充电次数

發布時間:2024/1/1 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2022CCSP T1最少充电次数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

記錄第一次CCSP競賽。一共3題,只做出第一題,用時3h30m(累),ac了開心地吃了個午飯。然而飯飽之后,大腦完全提不起神看著題面昏昏欲睡。第二題是虛擬內存,超級大模擬,剛好這個學期學os,但是翹了太多課完全看不懂,自己看ppt學了一點多級頁表,但是1v0,1v1啥的想不明白怎么對應呀。第三題跟數據庫系統有關,高性能 RDF 圖查詢系統,給了一個代碼框架,稍微看了看,代碼十分規范,應用了很多C++繼承、虛基類等等特性,然后按要求實現一些函數方法,不會。下面主要記錄第一題的思路。


T1 最少充電次數

題面


數據范圍

思路

DP,有電量、充電時間兩個維度約束,一開始我定義的狀態是 dp[n][rtime][rbat]dp[n][rtime][rbat]dp[n][rtime][rbat],維度的含義是當前站點、剩余充電時間和剩余電量,存儲相應的最小充電次數,但是更新該狀態數組會發現剩余電量這一維度是 (1<<30)≈1e9(1<<30)\approx1e9(1<<30)1e9,這肯定T飛。

其實看到問題很容易產生貪心想法,選擇充電效率較高的充電站以在相同的時間內獲得更多電量。那其他維度相同的狀態中是不是應選擇剩余電量更多的狀態?想到這點,重新定義狀態 dp[n][rtime][ans]dp[n][rtime][ans]dp[n][rtime][ans],調換一下,最后一維表示充電次數,數組存儲最大剩余電量。
遞推分為行駛和充電,由于當前狀態僅僅和前面一個狀態有關,將第一維度賦為2,滾動數組以壓縮空間。
① 行駛至下一個充電站:

dp[s ^ 1][j][k] = max(dp[s ^ 1][j][k], dp[s][j][k] - d[i + 1] + d[i]);

② 充電:

dp[s ^ 1][j][k] = dp[s][j][k]; // t==0 dp[s ^ 1][j - t][k + 1] = max(dp[s ^ 1][j - t][k + 1], dp[s][j][k] + t * cspeed[i]); // t!=0

優化

仔細算一下復雜度,充電站數×總最大充電時間×充電次數,512×1e4×512≈2.5e9512\times1e4\times512\approx2.5e9512×1e4×5122.5e9,提交上去只能過前面兩個點。
然后,開始想辦法借助STL進行優化(感覺CCF比賽我總是靠亂搞STL出奇跡)。
用數組存儲狀態,你只能按下標進行遞推,但這會冗余考慮很多不可能的狀態,從不可能的狀態遞推怎么也無法到達可能的狀態。于是乎我改用 map<node,int>stat[2]map<node, int> stat[2]map<node,int>stat[2],其中 node 的定義為

struct node {int rtime, cnt;bool operator < (const node &d) const {return cnt < d.cnt;} };

這個結構僅僅存儲有效狀態,因而我們也只會從有效狀態開始遞推,避免冗余。

AC代碼


太菜了,一發AC高興得不得來了。。。

#include <bits/stdc++.h> using namespace std; using ll = long long;int d[550], tlimit[550], cspeed[550];struct node {int rtime, cnt;bool operator < (const node &d) const {return cnt < d.cnt;} }; // 只對有效狀態進行轉移 map<node, int> stat[2];void solve() {int totdis, n, maxtime, initbat;cin >> totdis >> n >> maxtime >> initbat;d[0] = 0;for (int i = 1; i <= n; i++) cin >> d[i];for (int i = 0; i < n; i++) cin >> tlimit[i];for (int i = 0; i < n; i++) cin >> cspeed[i];stat[1][{maxtime, 0}] = initbat;int s = 1;for (int i = 0; i < n; i++) {// 從i-1行駛至ifor (const auto &[x, r] : stat[s]) {if (stat[s][x] - d[i + 1] + d[i] >= 0) {stat[s ^ 1][x] = stat[s][x] - d[i + 1] + d[i];}}stat[s].clear();s ^= 1;// 充電for (int t = 0; t <= tlimit[i]; t++) {// 狀態轉移for (const auto &[x, r] : stat[s]) {if (x.rtime < t) continue;if (t) {int tmp = 0;if (stat[s ^ 1][{x.rtime - t, x.cnt + 1}]) {tmp = stat[s ^ 1][{x.rtime - t, x.cnt + 1}];}stat[s ^ 1][{x.rtime - t, x.cnt + 1}] = max(tmp, r + t * cspeed[i]);}else { stat[s ^ 1][{x.rtime, x.cnt}] = r; }}}stat[s].clear();s ^= 1;}// ansfor (const auto &[x, r] : stat[s]) {if (r >= totdis - d[n]) {cout << x.cnt << '\n';return;}}{ cout << "-1\n"; } }int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);solve();return 0; }

提交代碼

僅僅作為個人記錄。

#include <bits/stdc++.h> using namespace std; using ll = long long; //#define Debug //#define arr // 選擇充電不一定會充至時間上限 // dp[n][rtime][rbat]:充電次數,(當前所在充電站、剩余充電時間、剩余電量) // 512*(1e4)*(1<<30) // 到達終點最少充電次數 /** dp[i][rtime][rbat]=dp[i-1][rtime][rbat+d[i]-d[i-1]]* dp[i][rtime-t][rbat+t*cspeed[i]]=dp[i][rtime][rbat]+1,t<=tlimit[i]*/// 分組背包 // 每組取物品個數=每個服務站充電時間 // 充電速度不同->選擇剩余電量最多的狀態 // dp[n][rtime][ans]/** dp[n][rtime][i]=max(dp[n][rtime+t][i-1]+t*cspeed[i])*/int d[550], tlimit[550], cspeed[550]; #ifdef arr int dp[2][10010][550]; // 該狀態下最大剩余電量 #else struct node {int rtime, cnt;bool operator < (const node &d) const {return cnt < d.cnt;} }; // 只對有效狀態進行轉移 map<node, int> stat[2]; #endifvoid solve() {int totdis, n, maxtime, initbat;cin >> totdis >> n >> maxtime >> initbat;d[0] = 0;for (int i = 1; i <= n; i++) cin >> d[i];for (int i = 0; i < n; i++) cin >> tlimit[i];for (int i = 0; i < n; i++) cin >> cspeed[i]; #ifdef arrmemset(dp, -1, sizeof dp);dp[1][maxtime][0] = initbat; // 初始化 #elsestat[1][{maxtime, 0}] = initbat; #endifint s = 1;for (int i = 0; i < n; i++) {// 從i-1行駛至i #ifdef arrfor (int j = maxtime; j >= 0; j--) {for (int k = 0; k <= i; k++) {dp[s ^ 1][j][k] = max(dp[s ^ 1][j][k], dp[s][j][k] - d[i + 1] + d[i]);}} #elsefor (const auto &[x, r] : stat[s]) {if (stat[s][x] - d[i + 1] + d[i] >= 0) {stat[s ^ 1][x] = stat[s][x] - d[i + 1] + d[i];}} #endif#ifdef Debugcout << "arrive: " << i << '\n'; // for (int j = maxtime; j >= 0; j--) { // cout << "rest time: " << j << '\n'; // for (int k = 0; k <= i && k <= n; k++) { // cout << "(" << k << "," << dp[s ^ 1][j][k] << ") "; // } // cout << '\n'; // } cout << '\n';for (const auto &x : stat[s ^ 1]) {cout << x.rtime << ' ' << x.cnt << ' ' << x.rbat << '\n';} cout << '\n'; #endif #ifdef arrmemset(dp[s], -1, sizeof dp[s]); #elsestat[s].clear(); #endifs ^= 1;// 充電for (int t = 0; t <= tlimit[i]; t++) {// 狀態轉移 #ifdef arrfor (int j = maxtime; j >= 0; j--) {if (j < t) break;for (int k = 0; k <= i && k <= n; k++) {if (!t) {dp[s ^ 1][j][k] = dp[s][j][k];}else {if (dp[s][j][k] < 0) continue;dp[s ^ 1][j - t][k + 1] = max(dp[s ^ 1][j - t][k + 1], dp[s][j][k] + t * cspeed[i]);}}} #elsefor (const auto &[x, r] : stat[s]) {if (x.rtime < t) continue;if (t) {int tmp = 0;if (stat[s ^ 1][{x.rtime - t, x.cnt + 1}]) {tmp = stat[s ^ 1][{x.rtime - t, x.cnt + 1}];}stat[s ^ 1][{x.rtime - t, x.cnt + 1}] = max(tmp, r + t * cspeed[i]);}else { stat[s ^ 1][{x.rtime, x.cnt}] = r; }} #endif}#ifdef Debugcout << "charge: " << i << '\n'; // for (int j = maxtime; j >= 0; j--) { // cout << "rest time: " << j << '\n'; // for (int k = 0; k <= (i + 1) && k <= n; k++) { // cout << "(" << k << "," << dp[s ^ 1][j][k] << ") "; // } // cout << '\n'; // } cout << '\n';for (const auto &x : stat[s ^ 1]) {cout << x.rtime << ' ' << x.cnt << ' ' << x.rbat << '\n';} cout << '\n'; #endif // memset(dp[s], -1, sizeof dp[s]);#ifdef arrmemset(dp[s], -1, sizeof dp[s]); #elsestat[s].clear(); #endifs ^= 1;}// ans #ifdef arrfor (int k = 0; k <= n; k++) {for (int j = maxtime; j >= 0; j--) {if (dp[s][j][k] >= totdis - d[n]) {cout << k << '\n';return;}}} #elsefor (const auto &[x, r] : stat[s]) {if (r >= totdis - d[n]) {cout << x.cnt << '\n';return;}} #endif{ cout << "-1\n"; } }int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);solve();return 0; }/* 10 2 2 2 3 8 1 1 2 310 2 2 5 3 8 1 1 3 2*/

總結

以上是生活随笔為你收集整理的2022CCSP T1最少充电次数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。