标签:越界 solution 方便 axel 怎么 联系 jin arc array
若有恒,何必三更眠五更起;
最无益,莫过一日曝十日寒。
最大值可以方便的转移,所以可以直接应用区间dp
为什么这里的状态转移不一样?
对比最经典的区间dp 题目 石子合并
dp[i][j]
状态定义不同
class Solution {
public:
int splitArray(vector<int>& nums, int m) {
int n = nums.size();
long long MAX = LLONG_MAX;
vector<vector<long long> > dp(n+1,vector<long long>(n+1,MAX));
vector<long long> sum(n+1,0);
for(int i = 0;i<n;i++){
sum[i+1] = sum[i] + nums[i];
}
for(int i = 0;i<=n;i++){
dp[0][i] = MAX;
}
dp[0][0] = 0;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=min(i,m);j++){
for(int k = 0;k<i;k++){
dp[i][j] = min(dp[i][j],max(dp[k][j-1],sum[i]-sum[k]));
}
}
}
return (int)dp[n][m];
}
};
验证方便(可以直接使用贪心策略)
分成m段的最大值的最小值
\[\text{given} \ m \\ans = \min(\max(\forall f())) \]-> 优化问题 -> 广义上是一个搜索解的问题,解空间是一定范围内的整数
??这里发现自己真的应该好好学逻辑,这种表示也不知道对不对,好蹩脚啊
采用贪心策略,尽可能少分,验证解是否合理(也就是判断一个解是不是在解空间里面)
bool test(vector<int> a,int s,int m){
int n = a.size();
int cnt = 0;
long long sum = 0;
for(int i = 0;i<n;i++){
sum += a[i];
if(sum>s){
cnt++;sum = a[i];
if(sum>s)return false;
continue;
}
}
cnt++;
return cnt<=m;
}
int splitArray(vector<int>& nums, int m) {
int n = nums.size();
long long sum = 0;
int _max = -1;
for(int i = 0;i<n;i++){
sum += nums[i];
_max = max(_max,nums[i]);
}
long long l = _max;
// long long l = 0;
long long r = sum;
long long mid;
while(l!=r){
mid = (l+r)/2;
if(test(nums,mid,m)){
r = mid;
}else{
l = mid + 1;
}
}
return l;
}
?? What about the longest non-decreasing path in a matrix?
int longestIncreasingPath(vector<vector<int>>& matrix) {
// 注意条件判断!
int n = max(matrix.size(),matrix[0].size());
// ...
}
class Solution {
public:
int di[4] = {1,0,-1,0};
int dj[4] = {0,1,0,-1};
int imax;
int jmax;
int ans = -7;
int l = 0;
bool check(int i,int j){
return (i>=0&&i<=imax&&j>=0&&j<=jmax);
}
int dfs(vector<vector<int>>& matrix,vector<vector<int>>& ms,
vector<vector<int>>& vis,int i,int j){
if(ms[i][j]!=-3){
return ms[i][j];
}
else{
int _ans = 0;
for(int k = 0;k<4;k++){
int ii = i+di[k];
int jj = j+dj[k];
if(check(ii,jj) && !vis[ii][jj] && matrix[ii][jj] > matrix[i][j]){
vis[ii][jj] = 1;
_ans = max(_ans,dfs(matrix,ms,vis,ii,jj)+1);
vis[ii][jj] = 0;
}
}
ms[i][j] = _ans;
return ms[i][j];
}
}
int longestIncreasingPath(vector<vector<int>>& matrix) {
if(matrix.size() == 0)return 0;
int n = max(matrix.size(),matrix[0].size());
vector<vector<int> > ms(n+10,vector<int>(n+10,-3));
vector<vector<int> > vis(n+10,vector<int>(n+10,0));
imax = matrix.size()-1;
jmax = matrix[0].size()-1;
for(int i = 0;i<matrix.size();i++){
for(int j = 0;j<matrix[i].size();j++){
ans = max(ans,dfs(matrix,ms,vis,i,j)+1);
}
}
return ans;
}
};
动态规划其实和记忆化搜索是同样的核心思想
最优子结构
&无后效性
&重复子问题
只不过记忆化搜索没有显式的状态转移
为了让大家更好地理解这道题,小编出了四道思考题,欢迎感兴趣的同学在评论区互动哦。
记忆化广度优先搜索
采用bfs的原因是因为目标就是要找到最优解,这种情况下dfs是没有边界的
?? 像这种情况下一定要注意利用短路求值方法,首先判断有没有数组越界
?? 复习一下在编译原理当中短路求值的实现方法
控制流的实现可以采用回填法
if ((a && b && c) || d) { do_something(); } if (a) { if (b) { if (c) { goto then_label; } else { goto else_label; } } else { goto else_label; } } else { else_label: if (d) { then_label: do_something(); } } //作者:RednaxelaFX //链接:https://www.zhihu.com/question/53273670/answer/134298223 //来源:知乎 //著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
bool check(int ii ){
return ii>=0 && ii<=N && vis[ii]==-1;
}
邻接表+HashMap
// Friend Chians
#include<stdio.h>
#include<queue>
#include<string.h>
#include<string>
#include<algorithm>
#include<iostream>
#include<map>
using namespace std;
const int MAX = 0x3f3f3f3f;
const int N = 1050;
int ans;
int w[N][N];
bool vis[N];
int dis[N][N];
vector<int >e[N];
int n;
map<string, int > m;
string buf;
string buf1,buf2;
void init(){
for(int i = 0;i<N;i++)vector<int >().swap(e[i]);
memset(w,0,sizeof(w));
memset(dis,0,sizeof(dis));
ans = -3;
for(int i = 0;i<N;i++){
for(int j =0;j<N;j++){
dis[i][j] = -3;
}
}
}
queue<int >q;
void bfs(int ori){
memset(vis,0,sizeof(vis));
queue<int> emp;
swap(emp,q);
dis[ori][ori] = 0;
vis[ori] = 1;
//
q.push(ori);
while(!q.empty()){
int cur = q.front();q.pop();
for(int i = 0;i<e[cur].size();i++){
int to = e[cur][i];
if(dis[ori][to]==-3 && !vis[to]){
dis[ori][to] = dis[ori][cur]+1;
q.push(to);
}
}
}
}
int main(){
while(1){
scanf("%d",&n);
init();
if(n==0) return 0;
else{
for(int i = 0;i<n;i++){
cin >> buf;
m[buf] = i;
}
}
//
int nn;
scanf("%d",&nn);
for(int i = 0;i<nn;i++){
cin >>buf1;
cin >>buf2;
int u = m[buf1];
int v = m[buf2];
e[u].push_back(v);
e[v].push_back(u);
}
// 输入完成
for(int i = 0;i<n;i++){
bfs(i);
}
ans = -MAX;
bool has = true;
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++){
if(dis[i][j] == -3){
printf("-1\n");
has = false;
break;
}else{
ans = max(ans,dis[i][j]);
}
}
if(!has)break;
}
if(!has)continue;
printf("%d\n",ans);
}
}
关键问题是如何评判一条路径,有多个评测尺度
题意的理解(后面的车不能用于前面的站点),这篇博客分析的很好
??这篇文章里面有一个神来之笔,想了好久没有头绪
所以用sent值来存储collect变化序列中最小的,当sent的值为负时,就代表需要从原点取自行车。
解决这个问题有一个朴素的思路
比如
when c/2 = 5 2 3 6 5 1 8 7 3 差值 -3 -2 1 0 -4 3 2 -2 累计差值 -3 -5 -4 -4 -8 -5 -3 -5 动作 sent 3 sent 2 collect 1 / sent
4-1 = 3collect collect 位置 极小
共sent
5最小
3 = -8-(-5)在每一次
delta
由负转正的时候,就做一次collect - need
,如果是复数,那么sent addtional bikes
,否则从collect
当中拿取。
??这里作者说的累计差值的全局最小就是所需借出的车子是什么意思呢?
凑合看吧 ??
累计值的意义是 一段时间内系统(好像有点高级hhh)将要向外界序求或者提供的资源。
最低的累计值意思就是,系统最多向外界需求的资源。
也就是说,当满足最低累计值之后,相当于满足了之前所有的需求(红色箭头),注意这里面存在系统自给自足的部分(累计值上升)。
也可以这样理解:相当于给系统一个橙色线所示的 势
,满足了系统自给自足的所有需求
啊,分析完了其实感觉还是没太分析到点子上
花了一两个小时啊~感觉效率挺低
我真的不太清楚原作者是怎么想到用这个指标来度量的~
柳婼大神其实是用了dfs 动态建立 temppath 并且模拟决策过程实现的,感觉这个还是现实一点~
但是那个累积最低值还是很神奇啊!
也叫双指针法
// POJ 3061
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100000 + 100;
const int MAX = 0x3f3f3f3f;
int n;
int s;
ll sum;
int a[N];
int main(){
int nn;
scanf("%d",&nn);
while(nn--){
scanf("%d %d",&n,&s);
for(int i = 0;i<n;i++){
scanf("%d",&a[i]);
}
int l = 0;
int r = 0;
int ans = MAX;
sum = 0;
while(1){
while(r<n&&sum<s)sum += a[r++];
if(sum<s)break;
ans = min(ans,r-l);
sum -= a[l++];
if(l>=n)break;
}
if(ans == MAX)printf("0\n");
else printf("%d\n",ans);
}
return 0;
}
// 80 Days
#include<stdio.h>
typedef long long ll;
const int N = 2000100;
int n;
int c;
int a[N];
int b[N];
int main(){
int nn;
scanf("%d",&nn);
while(nn--){
scanf("%d %d",&n,&c);
ll sum = c;
for(int i = 0;i<n;i++){
scanf("%d",&a[i]);
}
for(int i = 0;i<n;i++){
scanf("%d",&b[i]);
}
for(int i = 0;i<n;i++){
a[i] = a[i]-b[i];
a[i+n] = a[i];
}
int l = 0;
int r = 0;
while(1){
while(r<2*n && sum >= 0 && r-l+1 <= n){
sum += a[r];
r ++;
}
if(sum>=0 && r-l+1 > n)break;
while(sum<0 && l<r && l<n){
// 不符合要求
sum -= a[l];
l ++;
}
if(l>=n)break;
}
if(l>=n)printf("-1\n");
else printf("%d\n",l+1);
}
}
两道尺取的题目分析一下
n
的区间就可以了标签:越界 solution 方便 axel 怎么 联系 jin arc array
原文地址:https://www.cnblogs.com/zxyfrank/p/13938910.html