hdu2235 机器人的容器
生活随笔
收集整理的這篇文章主要介紹了
hdu2235 机器人的容器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
機器人的容器
Time Limit: 3000/3000 MS (Java/Others) ? ?Memory Limit: 32768/32768 K?(Java/Others)
Total Submission(s): 171 ? ?Accepted Submission(s): 33
Problem Description
這是一個n*m的矩形,矩形的每一個單位格子上的高度為h(0<=h<1000),請問這個容器容量
Input
輸入一個正整數T表示有T組數據
對于每組數據第一行輸入兩個正整數n,m(0<n,m<500)表示矩陣的大小。
接下來有n行,每行m個整數h。
Output
對于每組輸入輸出一個整數表示容量。
4 4
1 1 1 1
1 0 0 1
1 0 0 1
1 1 1 1
?
Sample Output
4
?
思路:
? ? ? 這個題目做了一個星期,不過感覺是個好題,感覺這個問題很實際,看到好題就特高興,
說下思路,一開始用了個很tle的方法,把每一個點都就是一層以層的來,對于沒一個點的每一層都是處理新圖,0,1看能不能跑出去,如果能ans++,時間復雜度大約是?500 * 500 * 1000 * 500 * 500,sb了,后來我想了下用二分去優化每一個點.二分去找每一個點的最大價值,500 * 500 * lg(1000) * 500 * 500照樣跪,說下ac的思路吧(網上的,看了好久想了好久才明白), 先把每一個點都獨立出來,按高度從小到大排序,如果高相等,就把是最外邊上的點放前面,這樣二級排序后我們就得到了一個序列,這個序列的最大特點就是任意兩個相鄰的點之間都沒有"空隙",就是沒有高度處于之間的柱子,(我表達不太明白,想一下就知道了),然后我們跑循環,我換個方式寫,容易明白
? ?如果當前的這個點沒有被標記過(標記過的點從此就沒有價值了,被標記就是當前可以流出去)
? ? {
? ? ? ?如果當前的這個點是邊緣上的點
? ? ? ?{
? ? ? ? ?那么直接從改點開始搜,吧所有沒標記過并且小于等于當前高度的點全都標記上 ? ?,標記的時候別忘了更新 ? ? ? ? ?下當前整個圖一共已經標記多少個了標記個數很有用..
? ? ? }
? ? ? 否則
? ? ? {
? ? ? ? 如果當前的點的相鄰四個點中有被標記過的,那么當前的這個點也就廢了,直接從當? 前的這個點開始,把小于 ? ? ? ? 等于他并且沒標記過的全標記上,標記上的都是廢的點..
? ? ? }
? ? ? 如果當前的高小于下一個高
? ? ? {
? ? ? ? (此時就有一個空隙,那么這個空隙的高度是node[i+1].h - node[i].h,空隙的寬度?是多少呢 ,其實就是當前開 ? ? ? ? 始往前沒有作廢的點)則 ans += (node[i+1].h - node[i].h) * (i - 作廢點的個數,作廢點的個數就是全 ?圖被標記 ? ? ? 的個數)
? ? }
}
機器人的容器
Time Limit: 3000/3000 MS (Java/Others) ? ?Memory Limit: 32768/32768 K?(Java/Others)
Total Submission(s): 171 ? ?Accepted Submission(s): 33
Problem Description
這是一個n*m的矩形,矩形的每一個單位格子上的高度為h(0<=h<1000),請問這個容器容量
Input
輸入一個正整數T表示有T組數據
對于每組數據第一行輸入兩個正整數n,m(0<n,m<500)表示矩陣的大小。
接下來有n行,每行m個整數h。
Output
對于每組輸入輸出一個整數表示容量。
?
Sample Input
14 4
1 1 1 1
1 0 0 1
1 0 0 1
1 1 1 1
?
Sample Output
4
?
思路:
? ? ? 這個題目做了一個星期,不過感覺是個好題,感覺這個問題很實際,看到好題就特高興,
說下思路,一開始用了個很tle的方法,把每一個點都就是一層以層的來,對于沒一個點的每一層都是處理新圖,0,1看能不能跑出去,如果能ans++,時間復雜度大約是?500 * 500 * 1000 * 500 * 500,sb了,后來我想了下用二分去優化每一個點.二分去找每一個點的最大價值,500 * 500 * lg(1000) * 500 * 500照樣跪,說下ac的思路吧(網上的,看了好久想了好久才明白), 先把每一個點都獨立出來,按高度從小到大排序,如果高相等,就把是最外邊上的點放前面,這樣二級排序后我們就得到了一個序列,這個序列的最大特點就是任意兩個相鄰的點之間都沒有"空隙",就是沒有高度處于之間的柱子,(我表達不太明白,想一下就知道了),然后我們跑循環,我換個方式寫,容易明白
for(i = 1 ;i <= n * m ;i ++)
{? ?如果當前的這個點沒有被標記過(標記過的點從此就沒有價值了,被標記就是當前可以流出去)
? ? {
? ? ? ?如果當前的這個點是邊緣上的點
? ? ? ?{
? ? ? ? ?那么直接從改點開始搜,吧所有沒標記過并且小于等于當前高度的點全都標記上 ? ?,標記的時候別忘了更新 ? ? ? ? ?下當前整個圖一共已經標記多少個了標記個數很有用..
? ? ? }
? ? ? 否則
? ? ? {
? ? ? ? 如果當前的點的相鄰四個點中有被標記過的,那么當前的這個點也就廢了,直接從當? 前的這個點開始,把小于 ? ? ? ? 等于他并且沒標記過的全標記上,標記上的都是廢的點..
? ? ? }
? ? ? 如果當前的高小于下一個高
? ? ? {
? ? ? ? (此時就有一個空隙,那么這個空隙的高度是node[i+1].h - node[i].h,空隙的寬度?是多少呢 ,其實就是當前開 ? ? ? ? 始往前沒有作廢的點)則 ans += (node[i+1].h - node[i].h) * (i - 作廢點的個數,作廢點的個數就是全 ?圖被標記 ? ? ? 的個數)
? ? }
}
如果沒明白我在說下,所謂的作廢點就是可以連接到邊緣上的點,因為排序了,高度越來越高,如果當前的這個點是作廢點,那么當前這個點和他所連接的作廢點一定是以后能連接到當前的點的作廢點,排序導致沒一個相鄰的高度差之間不會有別的高度的東西出現.當前的高度差*當前點個數-作廢點個數就是當前這一層的價值...這個題目很贊...天天圖論,做做這個也挺好..
#include<stdio.h> #include<string.h> #include<algorithm>#define N_n 505 #define N_N 250050 using namespace std;typedef struct {int x ,y;int high;int key; }NODE;NODE node[N_N]; int H[N_n][N_n]; int mark[N_n][N_n]; int now_mksum; int dir[4][2] = {0 ,1 ,0 ,-1 ,1 ,0 ,-1 ,0}; int n ,m;bool camp(NODE a ,NODE b) {return a.high < b.high || a.high == b.high && a.key > b.key; }bool ok(int x ,int y ,int now_h) {if(x >= 1 && x <= n && y >= 1 && y <= m && !mark[x][y] && H[x][y] <= now_h)return 1;return 0; }void MK(int x ,int y ,int now_h) {for(int i = 0 ;i < 4 ;i ++){int xx = x + dir[i][0];int yy = y + dir[i][1];if(ok(xx ,yy ,now_h)){mark[xx][yy] = 1;now_mksum ++;MK(xx ,yy ,now_h);}}return; }void jude(int x ,int y ,int now_h) {for(int i = 0 ;i < 4 ;i ++){int xx = x + dir[i][0];int yy = y + dir[i][1];if(xx == 0 || xx == n + 1 || yy == 0 || yy == m + 1)continue; if(mark[xx][yy]){ mark[x][y] = 1;now_mksum ++; MK(x ,y ,now_h); break;}} }int main () {int t ,i ,j ,ans;scanf("%d" ,&t);while(t--){scanf("%d %d" ,&n ,&m);for(i = 1 ;i <= n ;i ++)for(j = 1 ;j <= m ;j ++){scanf("%d" ,&H[i][j]);int now = (i - 1) * m + j;node[now].x = i;node[now].y = j;node[now].high = H[i][j];node[now].key = (i == 1 || i == n || j == 1 || j == m);}sort(node + 1 ,node + n * m + 1 ,camp);memset(mark ,0 ,sizeof(mark));for(ans = now_mksum = 0 ,i = 1 ;i <= n * m ;i ++){if(node[i].high == node[n*m].high) break;if(!mark[node[i].x][node[i].y]){if(node[i].key) {mark[node[i].x][node[i].y] = 1;now_mksum ++;MK(node[i].x ,node[i].y ,node[i].high);}else jude(node[i].x ,node[i].y ,node[i].high);}if(node[i].high < node[i+1].high)ans += ((node[i+1].high - node[i].high) * (i - now_mksum));}printf("%d\n" ,ans);}return 0; }
總結
以上是生活随笔為你收集整理的hdu2235 机器人的容器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu3786 Floyd或搜索 水题
- 下一篇: hdu3768 spfa+全排列