hihocoder 1035 自駕旅行 III

2022-05-11 04:36:11 字數 2371 閱讀 4480

描述

給定一棵含有 n 個結點的樹,結點從 1 標號。你從 1 號結點駕車出發,希望遍歷一些關鍵結點(訪問到就好,不需要按照這些關鍵結點的輸入順序)。每條邊有兩個權值,c0, c1 分別表示步行和駕車經過這條邊的代價。每次你可以選擇駕車經過一條邊(當且僅當有車),或者將車停放在當前所在的結點(如果有車),步行經過一條邊。

求遍歷完所有關鍵結點的最少代價。

注意: 你可以在任意結點結束遍歷,即使當前沒有車。

解題報告:

用時:2h20min,1re1wa

這題做的不是很好,首先看到題目思考了許久找不到好一點的狀態,然後參考了題解的狀態

\(f[x][0/1/2/3/4]\)表示x子樹內所有的關鍵點都已經走完的5中狀態的最小代價

\(f[x][0]\)表示只考慮人走,且人必須回到x的最小代價

\(f[x][1]\)表示只考慮人走,且人可以不回來的最小代價(用於f[x][4]的轉移)

\(f[x][2]\)表示人車一起走,且兩者都回來的最小代價

\(f[x][3]\)表示人車一起走,且人回車不回的最小代價(用於f[x][4]的轉移)

\(f[x][4]\)表示人車一起走,最後兩者都不回來的最小代價

在自己做的時候並沒有定義到\(f[x][3]\)這個狀態,然後發現\(f[x][4]\)是可以借助\(f[x][3]\)轉移的

設\(dis\)為該邊人走的代價,\(dis0\)為車走的代價,\(u\)為x的子節點

\(f[x][0]=\sum_f[u][0]+2*dis\)

\(f[x][2]=\sum_min(f[u][2]+2*dis0,f[u][0]+2*dis)\)

這兩個比較顯然,對於\(f[x][2]\)你可以帶著車一起走完回來,也可以把車放在原地,走完回來

設\(t=(f[u][2]+2*dis0,f[u][0]+2*dis)\)

\(f[x][1]\)就是某乙個子節點走的是\(f[u][1]+dis\),其他節點走的是\(t\)

\(f[x][3]\)同理,某乙個點走\(f[u][3]+dis+dis0\),其他點走\(t\)

顯然這兩個節點的特殊節點的選擇都是選擇貢獻最大的,即\(f[u][1]+dis\)和\(f[u][0]+dis*2\)做差後最大的乙個

對於\(f[x][4]\)兩者都不回,我們要分情況討論:

1.在遍歷最後一顆子樹時,有車

顯然遍歷之前是\(f[x][3]\),然後可以選擇最後一顆子樹是開車還是不開車對應\(f[u][1]\)和\(f[u][4]\)

2.若此時沒有車

遍歷之前狀態是\(f[x][2]\),其中某個子樹是\(f[u][3]\),表示車沒有回來人回來了,然後和上面一種情況不同的是:只能選擇人走了,那麼就是在不同於選擇了\(f[u][3]\)的子樹中再選擇乙個走\(f[v][1]\)

乙個我沒注意到的細節:

如果u同於v,那麼應該記錄乙個次小值,不然就會少一組轉移

#include #include #include #include #include #include #define rg register

#define il inline

#define iter iterator

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)<(b)?(a):(b))

using namespace std;

typedef long long ll;

const int n=1e6+5;

int head[n],num=0,to[n<<1],nxt[n<<1],dis[n<<1],dis0[n<<1];

void link(int x,int y,int d,int d0)

int gi()

int n,m;bool vis[n],mark[n];ll f[n][5];

void dfs(int x,int last)

else if(tmpf3=min(f3,min(f[u][4]+dis0[i],f[u][1]+dis[i])-t);

} f[x][1]=f[x][0]+f1;

f[x][3]=f[x][2]+f2;

f[x][4]=f[x][2]+f3;

f[x][4]=min(f[x][4],f[x][3]);

for(int i=head[x];i;i=nxt[i])

}void work()

m=gi();

for(int i=1;i<=m;i++)

dfs(1,1);

printf("%lld\n",min(f[1][4],f[1][0]));

}int main()

1035 插入與歸併

題目是pat乙級 思路 簡單修改插入排序和合併排序源 加入和目標比較若相等,就退出。注意 插入排序不是從第0個元素開始,是從第1個元素開始的。訓練目的 插入排序 合併排序 題目描述 根據維基百科的定義 插入排序是迭代演算法,逐一獲得輸入資料,逐步產生有序的輸出序列。每步迭代中,演算法從輸入序列中取出...

1035 插入與歸併

時間限制 200 ms 記憶體限制 65536 kb 長度限制 8000 b 判題程式 standard 作者 chen,yue 根據維基百科的定義 插入排序是迭代演算法,逐一獲得輸入資料,逐步產生有序的輸出序列。每步迭代中,演算法從輸入序列中取出一元素,將之插入有序序列中正確的位置。如此迭代直到全...

1035 插入與歸併

1035 插入與歸併 25 分 根據維基百科的定義 插入排序是迭代演算法,逐一獲得輸入資料,逐步產生有序的輸出序列。每步迭代中,演算法從輸入序列中取出一元素,將之插入有序序列中正確的位置。如此迭代直到全部元素有序。歸併排序進行如下迭代操作 首先將原始序列看成 n 個只包含 1 個元素的有序子串行,然...