資源限制
時間限制:1.0s 內存限制:256.0MB
問題描述
如下圖所示,3 x 3 的格子中填寫了一些整數。
±-–±-+
|10 1|52|
±-***–+
|20|30 1|
*******–+
| 1| 2| 3|
±-±-±-+
我們沿着圖中的星號線剪開,得到兩個部分,每個部分的數字和都是60。
本題的要求就是請你編程判定:對給定的m x n 的格子中的整數,是否可以分割爲兩個部分,使得這兩個區域的數字和相等。
如果存在多種解答,請輸出包含左上角格子的那個區域包含的格子的最小數目。
如果無法分割,則輸出 0。
輸入格式
程序先讀入兩個整數 m n 用空格分割 (m,n<10)。
表示表格的寬度和高度。
接下來是n行,每行m個正整數,用空格分開。每個整數不大於10000。
輸出格式
輸出一個整數,表示在所有解中,包含左上角的分割區可能包含的最小的格子數目。
樣例輸入1
3 3
10 1 52
20 30 1
1 2 3
樣例輸出1
3
樣例輸入2
4 3
1 1 1 1
1 30 80 2
1 1 1 100
樣例輸出2
10
分析:
舉例第二個:
最終輸出的答案是10,就是紅色塊塊的個數。題目要求是輸出包含左上角的最少塊數。
我們可以讓搜索從左上角出發,這樣遍歷出來的每一種方案都是包含左上角塊塊的。
深搜的過程中,肯定要滿足的是,搜出來的方案和是總和的一半。所以在輸入數據的時候就將總和算出來。然後在深搜到大於總和的一半的值時候,就可以剪枝。
深搜的時候,可以上下左右。只要這個數字沒有用過。
深搜的出口是當搜到的和是總和一半的時候。
AC代碼:
while True:
try:
# n行m列
m, n = map(int, input().split())
s = []
Sum = 0
for i in range(n):
s.append(list(map(int, input().split())))
Sum += sum(s[i])
used = [[0 for i in range(m)] for j in range(n)]
ans = 100
def dfs(i, j, temp_sum, cnt):
global ans
if temp_sum > Sum // 2:
return
if temp_sum == Sum // 2:
ans = min(ans, cnt)
return
used[i][j] = 1
# 如果現在不是最後一行,那麼可以往下走
if i + 1 < n and used[i+1][j] == 0:
dfs(i + 1, j, temp_sum + s[i][j], cnt + 1)
# 如果現在不是最頂上的一行,那麼可以往上走
if i - 1 >= 0 and used[i - 1][j] == 0:
dfs(i - 1, j, temp_sum + s[i][j], cnt + 1)
# 如果現在不是最左邊的一列,那麼可以往左邊走
if j - 1 >= 0 and used[i][j - 1] == 0:
dfs(i, j - 1, temp_sum + s[i][j], cnt + 1)
# 如果現在不是最右邊的一列,那麼可以往右邊走
if j + 1 < m and used[i][j + 1] == 0:
dfs(i, j + 1, temp_sum + s[i][j], cnt + 1)
# 執行到這說明s[i][j]這個數字不行,還原爲未使用狀態
used[i][j] = 0
dfs(0, 0, 0, 0)
if ans<100:
print(ans)
else:
print(0)
except:
break
編程小白歡迎指點~