블로그에 대한 최초의 파렴치한 선전 \ (\ wwwwww)
기사 목록 - 핵융합 원자로 노심 - 루오 Gubo 오프
지식 : \ (민주당 \) 최적화, 모노톤 큐
질문의 의미 :
\ ((N \ 시간 M) \) 의 매트릭스 크기
점의 부분 행렬 값과는
출발점으로, 임의의 위치를 첫 번째 행을 선택할 수있다.현재 위치 들어 \ ((I, J) \\) (단면으로 도시 \ (I는 \) 행 \ (J \) 열)
로 전송 될 수있다 : \ ((I + 1, \ [JT, T + J를. ] \) \) 임의의 지점에 (\ (JT> 0 \
\의 J + t \ leqslant M) \) 와 현재 위치의 위치 값이 획득된다.요구 사항 : 달성 할 수있는 최대 값과
샘플 설명 :
1. 성령에서 꿈 \ ((1,1) \) 출발 :의 총 가치 \ (+ 3 \)는 지금 \ (3 \)
2. 영적 꿈에 이동 (\) (2,2) \ : 총 가치를 \ (3 + \)은 지금 \ (6 \)
3. Reimu가 진행 \ ((3,3) \) : 합계 값 \ (3 + \) 지금 \ (9 \)
따라서, 총 값 뿐만 \ (9 \)
문제의 의미 분석 :
분명히 이것은이다 \는 (DP \)의
상태 천이 방정식은 매우 간단하다
사용 \ ([I]은 [J f를 ] \) 포인트 나타내는 \을 ((나는 J) \ ) 의 최대 값에 도달 할 수
있다 : \ (F [I] [J ] = 최대 (F [I-1] [K]) + V [I] [J] \에서 \ (케이 \ [JT, J + T] \) \)- 폭력 :
모든 점 직접 열거하고 그 점을 열거 전송할 수?
복잡성 \ (O (N ^ 3) \) 레벨
\ (40 부 \) 손
최적화를 고려 :
- 실측치 :
제 \ (I는 \) 행의 점 \ (F [] [] \) , 첫 번째 (\ I-1) \ 행 관련된
수있는 각각의 두 인접 행 고려 중 각 스플릿 :
도표 :
그것은 찾을 수 있습니다 :전송 포인트 \ ((I, J) \ ) 포인트
위한 \ (I-1 \) 라인 간격 \ (\ 밑줄 {[JT, J + T]} \) 에서 \ (F [] [] \) 최대의 포인트전송 포인트 \ ((I, J + 1 ) \) 포인트
위한 \ (I-1 \) 라인 간격 \ (\ 밑줄 {[J = T + 1, J + T + 1]} \) 의 , \ (F [] [] \) 의 최대 점전환점 ((I, J + 2) \) \ 점이
된다 \ (I-1 \) 라인 간격 \ (\ 밑줄 {[J = T, T + J + 2 + 2]} \) 의 , \ (F [] [] \) 의 최대 점
이 개 간격 이후
에 통해 간격이 될 수 하나 개의 단위로 권리를 얻을
이 우리가 다른 질문을 생각하게 P1886 슬라이딩 창
, 당신은 단조로운 큐를 배운하지 않은 경우이 기사를 추천 :
[로스 밸리 매일 # 9 ] [Sweetlemon] 꽃으로 OI 고등학교 팀은 투쟁 - 단조로운 큐에이 슬라이딩 윈도우 타입 최대 문제는
물론, 모노톤 큐가 유지 될 수있다.위의에서, 우리는 적절한 발견 \ (DP \) 단조로운 큐 최적화 : 최적화.
- 폭력 :
알고리즘 :
하는 업데이트 이제 가정 (내가 \) \ 라인 :
- 모노톤 초기화 큐
업데이트 할 수 \ ((I, 1) \ ) 포인트 \ ((I, K) (K \의 [1,1 + T]) \) ,
첨가 모노톤 큐
- 주기, 업데이트 시작 \ ([1, M]을 \ ) 각 지점에서 :
- 로 전송할 수 있습니다 \ (J \) 오른쪽 포인트 \ ((. 1-I, J + T) \) , 큐에
- 단조 큐에 전달 될 수 실측치 (J \) \ 최대 점의 \을 (F [] [] \)
- 최대로 \ (F [] [] \) 업데이트 \ (F [I] [J ] \)
- 로 전송할 수 있습니다 \ (J \) 오른쪽 포인트 \ ((. 1-I, J + T) \) , 큐에
- 모노톤 빈 큐 외층으로 순환 제 업데이트 \ (ⅰ + 1 \) 라인
마지막으로, 최종 라인 찾아
최대의 \ (F [N] [J] \) ,
즉을 최고 값을 구한다.- 모노톤 초기화 큐
코드에서 :
아날로그 어레이 필기 큐를 사용하기 때문에,
간단히 제 소자와 팀 헤드 및 테일 포인터를 비우는 재설정.
상수 비트 완화 \ (양단 큐의 \)를
#include<cstdio>
#include<ctype.h>
#include<cstring>
#define int long long
#define max(a,b) a>b?a:b
//=====================================
const int MARX = 4e3+10;
int n,m,k,t, now,ans;
int f[MARX][MARX];
int head=1,tail=1;//手写双端队列
int q[MARX]={9223372036854775807};//为q[0]赋一个极大值,来防止插入元素时越界
//=====================================
inline int read()
{
int fl=1,w=0;char ch=getchar();
while(!isdigit(ch) && ch!='-') ch=getchar();
if(ch=='-') fl=-1;
while(isdigit(ch)){w=w*10+ch-'0',ch=getchar();}
return fl*w;
}
void in(int x)//向单调队列中插入元素
{
while(f[now-1][x]>f[now-1][q[tail]] && tail>=head)
tail--;//取出队尾小于插入元素的数 , 以保证单调性
q[++tail]=x;//插入队尾
}
int find(int x)//查询元素
{
if(x+t<=m)in(x+t);//将能转移到x点 的 最后一个元素 x+t 插入队列
while(q[head]+t<x) head++;//找到队首第一个能够转移到x的点
return q[head];
}
//=====================================
signed main()
{
n=read(),m=read(),k=read(),t=read();
while(k--)
{
int x=read(),y=read(),w=read();
f[x][y]=w;
}
for(now=2;now<=n;now++)//从第二行,开始转移
{
for(int i=1;i<=t;i++) in(i);//初始化单调队列 , 满足能够 转移j=1的点
for(int j=1;j<=m;j++) f[now][j]+=f[now-1][find(j)];// 进行转移
head=tail=1 , q[1]=0;//清空队列
}
for(int i=1;i<=m;i++)//取得最大值
ans=max(ans,f[n][i]);
printf("%lld",ans);
}
문제이 완벽한 솔루션, 동양 공공 믿음 \ (+ \)