B1277 [HNOI2002]Tinux系统 树形dp
這個(gè)題bzoj上沒有圖,luogu上樣例有問題。。。其實(shí)這個(gè)題代碼不難,但是思考起來還是有一定難度的,其實(shí)這些題的重點(diǎn)都在于思考。我就不寫了,洛谷上唯一的題解寫的挺好,大家可以看一看。
題干:
在dos系統(tǒng)誕生以前,美國曾研究出一種類似的操作系統(tǒng),名為Tinux系統(tǒng)。但由于硬件設(shè)施的制約,Tinux系統(tǒng)有許多的缺點(diǎn)。下面就對(duì)Tinux系統(tǒng)作一個(gè)簡單的介紹:
Tinux系統(tǒng)是Tiger博士為美國軍方研制開發(fā)的一種操作系統(tǒng),該系統(tǒng)對(duì)文件的存儲(chǔ)方式類似于dos系統(tǒng),像一棵樹一樣,每一個(gè)葉子節(jié)點(diǎn)表示一個(gè)文件,每一個(gè)非葉子節(jié)點(diǎn)表示一個(gè)目錄。其中定義i級(jí)子目錄表示從根目錄開始訪問,一直訪問到該子目錄(不包括該子目錄)需要訪問的目錄的個(gè)數(shù)為i的目錄,所以根目錄下的目錄為一級(jí)子目錄,其他的目錄以此類推。但是在同一子目錄下,受到硬件的制約Tinux系統(tǒng)最多只能夠存儲(chǔ)k個(gè)文件或子目錄,也就是說這棵樹里面的每一個(gè)非葉子節(jié)點(diǎn)最多只有k個(gè)子節(jié)點(diǎn)。這樣就導(dǎo)致在文件數(shù)量較多的情況下,訪問存儲(chǔ)在該系統(tǒng)當(dāng)中的文件A,往往要先訪問一系列的子目錄,我們稱這些子目錄為文件A的上級(jí)目錄。例如下面這一個(gè)例子:
Root ? A1
? A2
? A3
? A4
? A4A1
? A4A2
? A4A2A1
? A4A2A2
? A4A3
當(dāng)我們要訪問文件A4A2A1時(shí)就必須先訪問它的上級(jí)目錄:一級(jí)子目錄A4和二級(jí)子目錄A4A2。
Tinux系統(tǒng)在存儲(chǔ)文件時(shí),給每一個(gè)子目錄都分配了k個(gè)指針,分別指向存放在該目錄下的每一個(gè)文件和每一個(gè)目錄,因此對(duì)文件的訪問實(shí)質(zhì)上就是對(duì)指針的訪問。但是由于硬件原因,這k個(gè)指針不盡相同,因此訪問它們的時(shí)間也不同,訪問第i個(gè)指針?biāo)馁M(fèi)的時(shí)間為 。但是對(duì)于兩個(gè)不同的子目錄(不管它們各自屬于哪一級(jí)目錄)而言它們各自所擁有的k個(gè)指針是相同的。
Tinux系統(tǒng)最大的缺點(diǎn)是訪問一個(gè)目錄時(shí),必須把該目錄下所有的文件讀入到內(nèi)存當(dāng)中來,這些文件包括在其各級(jí)子目錄當(dāng)中的文件,例如上面那一個(gè)例子,訪問A4那一個(gè)目錄,就必須把A4A1,A4A2A1,A4A2A2,A4A3這四個(gè)文件都讀入到內(nèi)存當(dāng)中來,訪問一個(gè)目錄所需要的時(shí)間為 (x表示該目錄及其各級(jí)子目錄下文件的個(gè)數(shù), 表示指向該目錄的指針的訪問時(shí)間)。因此根據(jù)上面介紹的訪問方法,單獨(dú)訪問一個(gè)文件所需要的總時(shí)間為訪問其所有上級(jí)目錄(不包括根目錄)所需要的時(shí)間與訪問指向該文件的指針?biāo)枰臅r(shí)間的和,例如上面那一個(gè)例子,訪問文件A4A2A1需要的時(shí)間=訪問目錄A4的時(shí)間+訪問目錄A4A2的時(shí)間+訪問指向文件A4A2A1的指針需要的時(shí)間。
現(xiàn)在,tiger博士準(zhǔn)備將n個(gè)文件存儲(chǔ)到一個(gè)空的Tinux系統(tǒng)當(dāng)中,希望你幫助他設(shè)計(jì)一個(gè)程序找到一種最優(yōu)的存儲(chǔ)方法,使得單獨(dú)訪問這n個(gè)文件所需要的時(shí)間總和最小。
輸入輸出格式
輸入格式:
輸入由文件”system.in”讀入。
文件的第一行為兩個(gè)正整數(shù) , ,接下來的k行每行有一個(gè)正整數(shù) 。
輸出格式:
輸出到文件”system.out”,輸出文件僅有一個(gè)正整數(shù),表示在最優(yōu)存儲(chǔ)方案下,單獨(dú)訪問這n個(gè)文件所需要的時(shí)間總和。(結(jié)果小于2的31次方 )
輸入輸出樣例
輸入樣例#1: 復(fù)制 4 3 3 5 4 4 輸出樣例#1: 復(fù)制 28說明
代碼:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) {char c;bool op = 0;while(c = getchar(), c < '0' || c > '9')if(c == '-') op = 1;x = c - '0';while(c = getchar(), c >= '0' && c <= '9')x = x * 10 + c - '0';if(op) x = -x; } template <class T> void write(T x) {if(x < 0) putchar('-'), x = -x;if(x >= 10) write(x / 10);putchar('0' + x % 10); } int f[1700][1700]; int n,k,p[1700]; int MIN(int x,int y) {if(!x)return y;elsereturn min(x,y); } int dp(int x,int y,int l) {if(x == 1){f[x][y] = p[y];return f[x][y];}if(y == k){f[x][y] = p[y] * x * x + dp(x,1,x - 1);return f[x][y];}int tmp = k - y + 1;if(tmp * l < x)return INF;if(f[x][y]) return f[x][y];tmp = (x - 1) / tmp + 1;duke(i,tmp,l){if(i == 1)f[x][y] = p[y] + dp(x - 1,y + 1,x - 2);elsef[x][y] = MIN(f[x][y],dp(x - i,y + 1,x - i - 1) + dp(i,1,i - 1) + p[y] * i * i);}return f[x][y]; } int main() {read(n);read(k);duke(i,1,k)read(p[i]);sort(p + 1,p + k + 1);printf("%d\n",dp(n,1,n - 1));return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/DukeLv/p/9726549.html
總結(jié)
以上是生活随笔為你收集整理的B1277 [HNOI2002]Tinux系统 树形dp的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【LeetCode】【数组归并】Merg
- 下一篇: api权限管理系统与前后端分离实践