乙個n×m的由非負整數構成的數字矩陣,你需要在其中取出若干個數字,使得取出的任意兩個數字不相鄰(若乙個數字在另外乙個數字相鄰8個格仔中的乙個即認為這兩個數字相鄰),求取出數字和最大是多少。
第1行有乙個正整數t,表示了有t組資料。
對於每一組資料,第一行有兩個正整數n和m,表示了數字矩陣為n行m列。
接下來n行,每行m個非負整數,描述了這個數字矩陣。
t行,每行乙個非負整數,輸出所求得的答案。
輸入 #1
3446775
6310
2929
9214
2168
7156867
912523
8770
8510317
3311
11991
111
輸出 #1
27117299
解題思路:
直接用dfs是會tle的(因為我直接用只跑通了4個測試樣例),平常dfs中我們會使用for迴圈來改變要訪問元素四個上下左右的位置,但是在此題中,dfs中套上for就會tle。因此需要有乙個更高效的移動方法:在此處,我們預設每次移動都是y+1;當時當y>m超過當前列數時,我們設定y=1(第一列)和x+1。由此看來,這個移動是固定的,而且我們可以知道下一步它的具體位置,在此方法中能確保所有位置都遍歷到。移動的終止條件是x>n超過行數時return。
我們對於每乙個位置都有取和不取值兩種情況(這樣就涵蓋了所有情況組合),從第乙個位置搜尋:取和不取先各來一次dfs。在dfs中,到達某個元素時,他有兩種狀態:能取和不能取,對於能取的:則取一次,標記為1表示取過,在dfs; 然後回溯標記0,再不取其值直接dfs,對於不能取的(表示周圍元素有被取過的): 直接dfs。
注意點:在這裡不應該找到某個位置,取其值後就立即把它周圍的元素給標記了,這樣會帶來很高的複雜度。dfs(x,y,sum)表示的是訪問到xy位置時的狀態,而且此時是否相加的情況也處理好了。因此
下面**的思路應該是訪問到某個元素後,先找到它下乙個要移動的位置,再去判斷該位置是否能取其值,若能則接下來有兩個dfs,若不能接下來有乙個dfs。
**:
1 #include2 #include3using
namespace
std;45
intn,m;
6int a[10][10]=;
7int map[10][10]=;89
int maxx=0; //
用來存放最大值
1011
12void dfs(int x,int y,int sum)
23if(mx>n) return; //
遞迴終止條件
2425
26if(!map[mx-1][my-1]&&!map[mx][my-1]&&!map[mx+1][my-1]&&!map[mx-1][my]&&!map[mx+1][my]&&!map[mx-1][my+1]&&!map[mx][my+1]&&!map[mx+1][my+1
])31
32dfs(mx,my,sum);
3334
return;35
}36intmain()
50}
5152 memset(map,0,sizeof
(map));
53 dfs(1,1,0
); //代表取當前第乙個數
54 memset(map,0,sizeof
(map));
55 map[1][1]=1
;56 dfs(1,1,a[1][1
]); //代表不取當前第乙個數
57 cout5859}60
return0;
61 }
洛谷 p1123取數遊戲
定義乙個dfs函式,函式有三個變數,分別是i,j,sum。i,j分別代表訪問的這個點的座標,sum表示這條路徑上的數字的和。思路是 從 1,1 這個點進入,依次以先列數增加,然後行數增加在訪問所有的點。如下 include include include using namespace std in...
洛谷 P1123 取數遊戲
洛谷傳送門 乙個n times mn m的由非負整數構成的數字矩陣,你需要在其中取出若干個數字,使得取出的任意兩個數字不相鄰 若乙個數字在另外乙個數字相鄰88個格仔中的乙個即認為這兩個數字相鄰 求取出數字和最大是多少。第1行有乙個正整數tt,表示了有tt組資料。對於每一組資料,第一行有兩個正整數nn...
洛谷 P1123 取數遊戲
乙個n m的由非負整數構成的數字矩陣,你需要在其中取出若干個數字,使得取出的任意兩個數字不相鄰 若乙個數字在另外乙個數字相鄰8個格仔中的乙個即認為這兩個數字相鄰 求取出數字和最大是多少。輸入格式 輸入第1行有乙個正整數t,表示了有t組資料。對於每一組資料,第1行有兩個正整數n和m,表示了數字矩陣為n...