1. 程式人生 > 實用技巧 >試題 歷屆試題 剪格子

試題 歷屆試題 剪格子

資源限制 時間限制: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 這題就是簡單的深搜. 先求出所有數的總和,判斷是否能被2整除,若不能就輸出0,能就再深搜判斷. 起初我否定了這個想法,因為這樣深搜只能找到以(0,0)為端點或者成環的劃分區域,但是並不排除有這樣的劃分區域:(0,0)不在這個區域的端點位置,而是交點位置,例如(0,0)所在行和列同屬於一個區域,其他數屬於另一個區域,這種劃分就搜不出來了. 不過百度了一下發現好多程式碼也沒考慮那麼多,交了之後發現原來就3個測試用例,我估計是水過.
 1
#include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <algorithm> 8 #define INF 0x3f3f3f3f 9 #define zero 1e-7 10 11 using namespace std; 12 typedef long long ll; 13 const ll mod=50000
; 14 const ll max_n=2e5+7; 15 16 int mp[10][10]; 17 bool vis[10][10]; //標記是否訪問過 18 int d[4][2]={{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; 19 int m, n;//n行m列 20 int ans, res;//所有數字和,最小區域格子數 21 22 void input() { 23 ans=0; 24 for(int i=0; i<n; i++) { 25 for(int j=0; j<m; j++) { 26 cin>>mp[i][j]; 27 ans+=mp[i][j]; 28 } 29 } 30 } 31 32 void dfs(int x, int y, int sum, int num) {//座標、區域和、區域格子數 33 vis[x][y]=true; 34 if(sum==ans/2) { 35 res=min(res, num); 36 return; 37 } 38 for(int i=0; i<4; i++) { 39 int dx=x+d[i][0]; 40 int dy=y+d[i][1]; 41 if(dx>=0 && dx<n && dy>=0 && dy<m && !vis[dx][dy] && sum+mp[dx][dy]<=ans/2) { 42 vis[dx][dy]=true; 43 dfs(dx, dy, sum+mp[dx][dy], num+1); 44 vis[dx][dy]=false;//回溯 45 } 46 } 47 } 48 49 int main() { 50 cin>>m>>n; 51 memset(vis, false, sizeof(vis)); 52 res=INF; 53 input(); 54 if(ans%2==0) dfs(0, 0, mp[0][0], 1); 55 if(res==INF) res=0; 56 cout<<res<<endl; 57 return 0; 58 }