C. Road Optimization-dp
题意:
给你n r k分别代表路标数、整段路长、最多可删除路标数
后面两行 每行n个数 分别代表 插有路标的位置 和 路标显示数 在(对于每小段路通过要用的时间是该段路长乘以该段开头的路标显示数)
要你求制定一个删路标的方案后 通过这段路的最少时间(起始路标不能删)
思路:
n就500 数据不大可用二维 dp
dp[i][j]代表 前i个路标移除j个通过该段路的最少时间 那么可以知道要从前一个状态转移的话 前一个状态的目标路标和 当前状态的目标路标之间的路标一定是移除的 不然就无法移除 那么就枚举k 代表两个状态之间已经删去的路标数 然后取最小的那个情况即可
#include<iostream> #include<algorithm> #include<string> #include<set> #include<map> #include<cstdio> #include<cmath> #include<cstring> #include<queue> #include<stack> #include<unordered_map> #include<iomanip> #define ll long long #define ull unsigned long long #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr) #define m_p make_pair #define pi acos(-1) using namespace std; const int N = 1e6 + 5; const int M = 5e5 + 5; const double eps = 1e-4; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; const ll mod = 1e9 + 7; ll a[510], b[510], dp[510][510], n, r, m; void solve() { cin >> n >> r >> m; for(int i = 1; i <= n; i++){ cin >> a[i]; } for(int i = 1; i <= n; i++){ cin >> b[i]; } //终点位置也要加上 a[n + 1] = r; //初始化 memset(dp, inf, sizeof(dp)); //第一个路标不能删初始为0 下一个循环i从2开始 for(int i = 0; i <= m; i++){ dp[1][i] = 0; } //i代表当前位置 for(int i = 2; i <= n + 1; i++){ //枚举删去路标数 for(int j = 0; j <= m; j++){ //枚举两个状态之间已经删去的路标数 j-k是前一个状态还需删去的路标数 for(int k = 0; k <= j; k++){ ll p = i - 1 - k; //前一个位置要大于等于0 if(p >= 0) dp[i][j] = min(dp[i][j], dp[p][j - k] + (a[i] - a[p] )* b[p]); } } } ll ans = inf; //再取最优解 for(int i = 0; i <= m; i++){ ans = min(ans, dp[n + 1][i]); } cout << ans << "\n"; } signed main() { IOS; ll t = 1; //cin >> t; while(t--) solve(); return 0; }