點我看題目
題意 :兩條平行線上分別有兩種城市的生存,一條線上是貧窮城市,他們每一座城市都剛好只缺乏一種物資,而另一條線上是富有城市,他們每一座城市剛好只富有一種物資,所以要從富有城市出口到貧窮城市,所以要修路,但是不能從富有的修到富有的也不能從貧窮的修到貧窮的,只能從富有的修到貧窮的,但是不允許修交叉路,所以問你最多能修多少條路。
題意 :這個題一開始我瞅了好久都沒覺得是DP,后來二師兄給講了一下才恍然大悟。其實就是用到了DP中的那個最長上升子序列,把題中貧窮城市的坐標當成數組的下標,跟其相連的富有城市的坐標當作數組的值,這樣的話,因為不能有交叉,所以只能一直往右,這就好比找最長上升子序列,因為用樸素的算法會超時所以要用二分。
解題報告這里邊的解釋非常詳細,就是怎么用二分去做,其實就是將找到的子序列保存到B數組里,但是往里插入的過程用的是二分。
?


//HDU 1025 #include <iostream> #include <stdio.h> #include <string.h>using namespace std;int dp[505000] ; int B[505000] ;int main() {int n ;int casee = 1 ;while(~scanf("%d",&n)){int a,b ;for(int i = 0 ; i < n ; i++){scanf("%d %d",&a,&b) ;dp[a] = b ;//這樣就相當于去找dp這個數組的最長上升子序列了 }int len = 1 ;B[1] = dp[1] ;for(int i = 2 ; i <= n ; i++)//這里掉了等號WA到死啊 {int low = 1 , high = len ;while(low <= high){int mid = (low+high) >> 1 ;if(B[mid] < dp[i]) low = mid+1 ;else high = mid - 1 ;}B[low] = dp[i] ;if(low > len) len++ ;}printf("Case %d:\n",casee++) ;if(len == 1)printf("My king, at most 1 road can be built.\n\n") ;else printf("My king, at most %d roads can be built.\n\n",len) ;}return 0; }
?