\(loj\) 放上了那麼多《資訊學奧賽一本通》上的題(雖然我並沒有這本書),我要給它點乙個大大的贊 _
以後分類刷題不愁啦!
那就一道道說吧。
將 \(n\) 堆石子繞圓形操場排放,現要將石子有序地合併成一堆。規定每次只能選相鄰的兩堆合併成新的一堆,並將新的一堆的石子數記做該次合併的得分。
求 \(n−1\) 次合併後得分總和的最大值和最小值。
\(n \leq 200\)
首先注意到「繞圓形排放」,那麼有乙個經典的技巧就是在 \(1 \sim n\) 後再接乙個 \(1 \sim n\) ,相當於把圓拆成一條直線
接著就是經典的區間 \(dp\) ,方程 \(f[i][j]=\mathop\limits_^ \\),最小值亦然
\(sum[i][j]\)為第 \(i\) 堆到第 \(j\) 堆石子數之和,可以用字首和算出來。
注意轉移的順序為區間大小從小至大。
#include#include#includeusing namespace std;
const int n = 405;
int n;
int f[n][n],g[n][n],s[n];
int main()
\limits_^ \\)
#include#include#includeusing namespace std;
const int n = 205;
typedef long long ll;
int n;
ll w[n],f[n][n];
int main()
\limits_^ \\)
坑人的是要寫高精度 \(qwq\)
#include#include#include#includeusing namespace std;
const int n = 55*2;
const int sz =1000;
struct bign
void print()
printf("\n");
} bign operator = (int x)
bign operator + (const bign &b) const
return c;
} bign operator * (const bign &b) const
g=c.s[i]+g;
c.s[i]=g%sz;
g/=sz;
} return c;
} bool operator > (const bign &b) const
}w[n],f[n][n],max;
int n;
int main()
bign m=max;
for(int i=1;i<=n;i++) if(m>f[i][i+n-1]) m=f[i][i+n-1];
m.print();
return 0;
}
\(be\) 中有一類被稱為 \(gbe\)。
以下是 \(gbe\) 的定義:
1.空表示式是 \(gbe\)
2.如果表示式 \(a\) 是 \(gbe\),則 \([a]\) 與 \((a)\) 都是 \(gbe\)
3.如果 \(a\) 與 \(b\) 都是 \(gbe\),那麼 \(ab\) 是 \(gbe\)
給定 \(be\) ,問最少新增多少字元可將其變為 \(gbe\)
字串長度小於100
這個就是很常規的區間\(dp\),感覺沒什麼好說的
對於 \(f[i][j]\) ,先討論 \(s[i]\) 與 \(s[j]\) 是否可湊成一對中括號或小括號,如果可以的話 \(f[i][j]=f[i+1][j-1]\)
接著 \(f[i][j]=\mathop\limits_^ \\)
#include#include#include#include#define inf 100007
using namespace std;
const int n = 105;
int n;
int f[n][n];
char s[n];
int main()
\limits_^ \\)
因為最後要輸出方案,所以每個區域要記錄下使 \(f[i][j]\) 取到 \(max\) 的 \(k\)
#include#include#includeusing namespace std;
const int n = 305;
typedef long long ll;
typedef pairp;
int n;
ll a[n],f[n][n];
int g[n][n];
int head,tail;
p que[n*n];
int main()
\) 均為非負整數。遊戲規則如下:
1.每次取數時必須從每行各取走乙個元素,共 \(n\) 個,\(m\) 次取完所有元素。
2.每次取走的各個元素只能是該元素所在行行首或行尾。
3.每次取數都有乙個的分值,為每行取數得分之和,每行取數得分=被取走元素值 \(\times 2^i\),其中 \(i\) 表示第 \(i\) 次取數,從 1 開始計數。
4.遊戲結束時,總得分為 \(m\) 次取數得分之和。
求取數後的最大得分。\(n,m \leq 80, a_ \leq 10^3\)
這個也沒啥難的,每行一次區間\(dp\)
方程 \(f[i][j]=max \ , f[i+1][j] +a[i] \times 2^ \}\)
噁心的是又要加高精度。
#include#include#include#includeusing namespace std;
const int n = 85;
const int sz = 10000;
struct bign
bign operator = (int x)
bign operator + (const bign &b) const
return c;
} bign operator * (const int &x) const
g=g+x*s[i];
c.s[i]=g%sz;
g/=sz;
} return c;
} bool operator < (const bign &b) const
printf("\n");
}}mod[n],f[n][n],ans;
int n,m;
int a[n];
int main()
ans=ans+f[1][m];
} ans.print();
return 0;
}
動態規劃之區間dp
動態規劃 dp 就是把把大問題轉化為乙個個小問題,然後在眾多的小問題中遞推得到這個大問題的最佳解 當然,這只是我個人對動態規劃的理解,希望有大牛來指導改正 那麼區間dp就是在區間之間進行動態規劃。那麼區間dp的典型例題就是 nyoj 15 括號配對 nyoj 737 石子合併 做區間dp的題的一般步...
區間DP 動態規劃 C
區間型別動態規劃是線性動態規劃的拓展,它在分階段劃分問題時,與階段中元素出現的順序和由前一階段的哪些元素合併而來有很大的關係。1 合併 即將兩個或多個部分進行整合。2 特徵 能將問題分解成為兩兩合併的形式。3 求解 對整個問題設最優值,列舉合併點,將問題分解成為左右兩個部分,最後將左右兩個部分的最優...
模板 動態規劃 區間dp
因為昨天在codeforces上設計的區間dp錯了 錯過了上紫的機會 覺得很難受。看看學長好像也有學,就不用看別的神犇的了。區間dp處理環的時候可以把序列延長一倍。for int len 1 len n len 首先,使用四邊形優化要滿足下面的性質 當小區間包含在大區間中,則小區間的成本不高於大區間...