10.27T2 线性DP+拆分
2.樹塔
(tower)
【問題描述】
相信大家都在長訓班學過樹塔問題,題目很簡單求最大化一個三角形數塔從上往下走的路徑和。走的規則是:(i,j)號點只能走向(i+1,j)或者(i+1,j+1)。如下圖是一個數塔,映射到該數塔上行走的規則為:從左上角的點開始,向下走或向右下走直到最底層結束。
? ?1
??3 8
??2 5 0
??1 4 3 8
??1 4 2 5 0
?? 路徑最大和是1+8+5+4+4 = 22,1+8+5+3+5 = 22或者1+8+0+8+5 = 22。
?? 小S覺得這個問題so easy。于是他提高了點難度,他每次ban掉一個點(即規定哪個點不能經過),然后詢問你不走該點的最大路徑和。
??當然他上一個詢問被ban掉的點過一個詢問會恢復(即每次他在原圖的基礎上ban掉一個點,而不是永久化的修改)。
【輸入】
第一行包括兩個正整數N,M,分別表示數塔的高和詢問次數。
??以下N行,第i行包括用空格隔開的i-1個數,描述一個高為N的數塔。
??而后M行,每行包括兩個數X,Y,表示第X行第Y列的數塔上的點被小S ban掉,無法通行。
??由于讀入數據較大,c或c++請使用較為快速的讀入方式。
【輸出】
M行每行包括一個非負整數,表示在原圖的基礎上ban掉一個點后的最大路徑和,如果被ban掉后不存在任意一條路徑,則輸出-1。
【輸入輸出樣例】
| tower.in | tower.out |
| 5 3 1 3 8 2 5 0 1 4 3 8 1 4 2 5 0 2 2 5 4 1 1 | 17 22 -1 |
【樣例解釋】
第一次是1
3 X
2 5 0
1 4 3 8
1 4 2 5 0
1+3+5+4+4 = 17 或者 1+3+5+3+5=17
第二次:
1
3 8
2 5 0
1 4 3 8
1 4 2 X 0
1+8+5+4+4 = 22
第三次:你們都懂的!無法通行,-1!
【數據規模和約定】
所有測試數據范圍和特點如下:
對于所有數據,數塔中的數X的大小滿足0≤X≤106
?
| 測試點編號 | N | M | 特殊約定 |
| 1 | ≤ 5 | ≤ 3 | ? |
| 2 | ? | ||
| 3 | ≤ 105 | ? | |
| 4 | ? | ||
| 5 | ≤ 50 | ≤ 103 | 滿足點(i,j)上的數=i*j |
| 6 | ? | ||
| 7 | ? | ||
| 8 | ? | ||
| 9 | ≤ 300 | ≤ 104 | 數塔中所有數相等 |
| 10 | ? | ||
| 11 | ? | ||
| 12 | ? | ||
| 13 | ≤ 1000 | ≤ 3*105 | 滿足點(i,j)上的數=i-j |
| 14 | 滿足點(i,j)上的數=i*j | ||
| 15 | 數塔中所有數相等 | ||
| 16 | ? | ||
| 17 | ? | ||
| 18 | 5*105 | 滿足點(i,j)上的數=i-j | |
| 19 | ? | ||
| 20 | ? |
?
?
?
?
?
這題我SB了,本應想到前后綴DP是可行的,但是我一直卡在去掉數字的影響導致65pt
考慮求出每一個位置從上到下的最大值和從小到大的最大值,枚舉去掉的那一行的前后綴和的最大值就可以了
暴力其實可以拿80但是我分段分的不好
code:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 long long a[1005][1005],suf[1005][1005],pre[1005][1005]; 5 long long read(){ 6 long long x=0,f=1;char c=getchar(); 7 while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} 8 while(isdigit(c)){x=(x<<3)+(x<<1)+c-'0';c=getchar();} 9 return x*f; 10 } 11 int main() { 12 long long n,m; 13 n=read(),m=read(); 14 for(long long i=1; i<=n; i++) 15 for(long long j=1; j<=i; j++) 16 a[i][j]=read(),suf[i][j]=max(suf[i-1][j],suf[i-1][j-1])+a[i][j]; 17 for(long long i=n; i>=1; i--) 18 for(long long j=1; j<=i; j++) 19 pre[i][j]=max(pre[i+1][j],pre[i+1][j+1])+a[i][j]; 20 for(long long i=1; i<=m; i++) { 21 long long x=read(),y=read(),max0=0; 22 if(x==1&&y==1) {cout<<-1<<'\n';continue;} 23 for(long long j=1; j<=x; j++) { 24 if(j==y)continue; 25 max0=max(max0,pre[x][j]+suf[x][j]-a[x][j]); 26 } 27 cout<<max0<<'\n'; 28 } 29 return 0; 30 }over
轉載于:https://www.cnblogs.com/saionjisekai/p/9860926.html
總結
以上是生活随笔為你收集整理的10.27T2 线性DP+拆分的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Algs4-2.1.37部分有序
- 下一篇: Angular和SAP C4C的事件处理