藍橋杯 剪格子
前言
半個月前,自己做藍橋2013年A組真題的時候,做到了剪格子這個題,由於對DFS不熟練,無從下手,自己花了接近一週的時間去重新學習遞迴和DFS,然後今天在看到這個題,就很簡單了。
正文
附上題目:
標題:剪格子
如圖所示,3 x 3 的格子中填寫了一些整數。
我們沿著圖中的紅色線剪開,得到兩個部分,每個部分的數字和都是60。
本題的要求就是請你程式設計判定:對給定的m x n 的格子中的整數,是否可以分割為兩個部分,使得這兩個區域的數字和相等。
如果存在多種解答,請輸出包含左上角格子的那個區域包含的格子的最小數目。
如果無法分割,則輸出 0
程式輸入輸出格式要求:
程式先讀入兩個整數 m n 用空格分割 (m,n<10)
表示表格的寬度和高度
接下來是n行,每行m個正整數,用空格分開。每個整數不大於10000
程式輸出:在所有解中,包含左上角的分割區可能包含的最小的格子數目。
例如:
使用者輸入:
3 3
10 1 52
20 30 1
1 2 3
則程式輸出:
3
再例如:
使用者輸入:
4 3
1 1 1 1
1 30 80 2
1 1 1 100
則程式輸出:
10
如下圖:
資源約定:
峰值記憶體消耗 < 64M
CPU消耗 < 5000ms
請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入…” 的多餘內容。
所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include , 不能通過工程設定而省略常用標頭檔案。
提交時,注意選擇所期望的編譯器型別。
分析
1.這個題在輸入的時候挖了一個坑,把n,m的順序顛倒了一下,這裡要注意。
2.沿著紅線剪開,其實就是把連續的格子裡面的數值累加起來,適合用DFS進行搜尋。
3.既然說如果有多種答案時,選擇包含第一個單元格的解法,那麼我們可以直接選擇第一個單元格進行DFS。
4.當單元格的數值累加大於表格內所有單元格之和時,我們就可以直接跳出當前遞迴,因此,我們可以提前把表格內所有單元格之和計算出來。
話不多說,直接附上程式碼:
package JA2013;
import java.util.Scanner;
public class _09剪格子 {
static int n ;
static int m;
//table 表示整個表格
static int [][] table;
//記錄解法最少格子的數目
static int minCnt = Integer.MAX_VALUE;
//記錄表格的總和
static int sum;
//記錄單元格是否被訪問
static int [][] isVi;
//記錄有多少個解法
static int ansCnt;
public static void main(String[] args) {
//變數初始化
Scanner sc = new Scanner(System.in);
m = sc.nextInt();
n = sc.nextInt();
table = new int[n][m];
isVi = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
table[i][j] = sc.nextInt();
sum += table[i][j];
}
}
//進行DFS
dfs(0,0,0,0);
//如果ansCnt等於0則表示無解,按照題目要求輸出0。
if (ansCnt!=0) {
System.out.println(minCnt);
}else {
System.out.println(ansCnt);
}
}
/**
*
* @param i i陣列下標
* @param j j陣列下標
* @param s 當前單元格數值累加值
* @param cnt 當前單元格計數器
*/
private static void dfs(int i, int j, int s,int cnt) {
//如果當前陣列下標越界
//如果單元格的數值累加大於表格內所有單元格之和
//如果當前單元格已訪問
if (i < 0 || j < 0 || i == n || j == m ||sum/2 < s ||isVi[i][j] == 1) {
return;
}
//如果當前單元格數值累加值等於表格內所有單元格之和時,表示找到一種解法
if (sum/2 == s) {
//記錄
minCnt = Math.min(minCnt,cnt);
ansCnt++;
return;
}
//標記已訪問當前單元格
isVi[i][j] = 1;
//分別右,下,左,上進行搜尋
dfs(i,j+1,table[i][j]+s,cnt+1);
dfs(i+1,j,table[i][j]+s,cnt+1);
dfs(i,j-1,table[i][j]+s,cnt+1);
dfs(i-1,j,table[i][j]+s,cnt+1);
//搜尋完成,進行回溯
isVi[i][j] = 0;
}
}
總結
這是一個經典的DFS題目,藍橋杯考遞迴和DFS非常頻繁,所以這個題值得去嘗試。
相關文章
- 【藍橋杯】試題 歷屆試題 剪格子(python解法+java解法)PythonJava
- 藍橋杯 演算法訓練 操作格子 (線段樹)演算法
- 藍橋杯
- 2016藍橋杯省賽第七題剪郵票
- 藍橋杯 買瓜
- 藍橋杯-分巧克力
- 藍橋杯-N皇后
- 藍橋杯真題
- 藍橋杯-長草(BFS)
- 藍橋杯-螞蟻感冒
- 藍橋杯-帶分數
- 藍橋杯-翻硬幣
- 藍橋杯-座次問題
- 藍橋杯-日期問題
- 藍橋杯 計算方程
- 藍橋杯-排列序數
- 如何準備藍橋杯
- 藍橋杯年號字串字串
- 藍橋杯考點整理
- 藍橋杯 分巧克力(Java)Java
- 藍橋杯訓練2
- 藍橋杯 整數拼接
- 藍橋杯注意的地方
- 藍橋杯學習路線
- 藍橋杯——查詢的妙趣
- 藍橋杯——巧妙地遞迴遞迴
- 藍橋杯-走迷宮(BFS)
- 藍橋杯-地宮取寶
- 藍橋杯-波動數列
- 藍橋杯-k倍區間
- 太陽(藍橋杯14屆)
- 藍橋杯-日誌統計
- 藍橋杯-合併數列
- 藍橋杯-班級活動
- 藍橋杯模板(二)python組Python
- 藍橋杯模板(三)python組Python
- 藍橋杯javaB組備賽Java
- 藍橋杯——暴力列舉篇