n(n≤100000)個平台上空有乙個鐵球,球每次落到某個平台上後,遊戲者可以選擇向左或向右滾,球滾動和落下的速度都是1。由於鐵球的質量不太好,每次落下的高度不能超過max。設計一種策略,使得球盡快落到地面而不被摔碎。假設地面高度為0,且無限寬。
第一行是兩個數n,max。
第二行兩個數,分別表示鐵球起始位置的橫縱座標。
接下來n行,第i行是三個正整數hi,li,ri,
輸入資料保證有解,且平台的高度互不相同、各邊緣與橫座標的值均互不相同。
僅乙個數,為鐵球到達地面的最短時間。
輸入 #1複製
5 3dp[i][0]=min(dp[i][0],dp[ch[i][0]][0]+la[i]-la[ch[i][0]]+a[i].h-a[ch[i][0]].h);dp[i][0]=min(dp[i][0],dp[ch[i][0]][1]+ra[ch[i][0]]-la[i]+a[i].h-a[ch[i][0]].h);dp[i][1]=min(dp[i][1],dp[ch[i][1]][0]+ra[i]-la[ch[i][1]]+a[i].h-a[ch[i][1]].h);dp[i][1]=min(dp[i][1],dp[ch[i][1]][1]+ra[ch[i][1]]-ra[i]+a[i].h-a[ch[i][1]].h);6 10
5 2 4
9 3 9
6 7 10
2 1 5
3 8 11
這題應該不難想到使用dp求解。
我們先將每塊木板按照高度排序。
然後我們按照從矮到高的順序倒序遍歷這些木板。
可能你會問為什麼要從矮到高的順序dp。
其實從高到到矮的順序dp,其實從高到矮並不是不可以。
但從低到高會來的更方便。
因為從低到高的話,我們只需要考慮從左邊下落到達的木板,和從右邊下落到達的兩個木板繼承就可以了。
然而從高到低我們並不方便找到哪些下落可以到達該木板。
以上都是廢話
假若我們已經求得了這個木板左右下落會到達哪些木板,
我們記 ch[i][1/0] 0表示i的左邊下落到達的木板,1表示右邊下落到達的木板。
dp[i][1/0] 0表示如果下落到左邊木板,最小費時,1表示下落到右邊木板的最小費時。
la[i] 表示 i 的右端點橫座標, ra[i] 表示 i 的左端點橫座標。
a[i].h 記錄 i 木板的高度。
dp 方程如下:
其實這後面轉移就是路徑的模擬,不難明白。
dp方程解決了,還有乙個問題,那就是如何處理出每個木板左右下落後到達的木板?
乙個比較好理解的方案是線段樹。
這裡使用了區間賦值和單點修改。
我們從低到高列舉木板,查詢左/右端點下線段樹上對應的值。
這值就是我們要求的落到的那個木板編號。
當這個木板完後,他就是對應區間(木板的左端點到右端點),最上面的木板了。
它上面的應當會落在它的上面。
於是區間修改。把這段區間的值修改為這個木板的編號。
到此,問題得到完美解決
等等,我們千萬不要忘記離散化,以及dp時特判。
如果當前的木板下落到的木板編號為0,那麼dp是當前木板的高度。
具體看**
#include#include#include
#include
#define ls k<<1
#define rs k<<1|1typedef
long
long
ll;using
namespace
std;
const
int n=1e6;
ll n,m,cnt;
ll lx[n
<<2],ch[n][2],w[n<<4],tag[n<<4
];//
ll la[n
<<2],ra[n<<2],dp[n][2
];//
struct
node
}a[n];
inline
void read(ll &x)
inline
void
update(ll k,ll x,ll y)
inline
void
change(ll k,ll x,ll y,ll l,ll r,ll val)
ll mid=x+y>>1
;
if(tag[k]) update(k,x,y);//區間賦值的標記下傳
change(ls,x,mid,l,r,val);
change(rs,mid+1
,y,l,r,val);
}inline ll query(ll k,ll x,ll y,ll pos)
intmain()
sort(lx+1,lx+cnt+1
);//離散化陣列排序
sort(a+1,a+1+n);//木板高度排序
for(i=1;i<=n;i++)
for(i=1;i<=n;i++)
memset(dp,
0x3f,sizeof
(dp));
dp[0][0]=dp[0][1]=0
;//顯而易見的初始化
for(i=1;i<=n;i++)
else dp[i][0]=a[i].h;
}if(a[i].h-a[ch[i][1]].h<=m)
else dp[i][1]=a[i].h;}}
printf("%d
",min(dp[n][0],dp[n][1
]));//最後答案為轉移到起始位置 n 的值。
}//剛好99行
14 4 選單功能
選單功能就是與使用者的溝通介面。1 在workermanager.h標頭檔案中新增show menu 成員函式。class workermanager 2 在workermanager.cpp中實現show menu 成員函式。其實這個函式就是在螢幕中把選單介面列印出來,沒什麼技術含量。顯示選單 v...
14 4 執行緒的通訊
執行緒通訊 乙個執行緒完成自己的任務時,就要通知另外乙個執行緒去 例子就是生產者與消費者關係 wait 等待。如果執行緒執行了wait方法,那麼該執行緒會進入等待的狀態 notify 喚醒等待的執行緒 注意 1 wait和notify方法是屬於objeck類的。2 wait和notify方法必須是要...
南陽144 某種序列
時間限制 3000 ms 記憶體限制 65535 kb 難度 4 描述 數列a滿足an an 1 an 2 an 3,n 3 編寫程式,給定a0,a1 和 a2,計算a99 輸入 輸入包含多行資料 每行資料報含3個整數a0,a1,a2 0 a0,a1,a2 100000000 資料以eof結束 輸出...