T:電路板導通問題(C++)
阿新 • • 發佈:2018-12-24
問題描述:
有一塊佈滿器件的電路板,器件共N行M列。每個器件只有兩種狀態,經一次鐳射照射後狀態反轉。
初始時,器件的狀態隨機。鐳射的位置在每列器件的最上方,這意味著照射一次,當前列中的所有器件的狀態全部反轉。(鐳射可以多次照射同一列。)
當一行中的所有器件全為1時,本行處於導通狀態。
給定一塊電路板,並指定鐳射照射次數,求最大導通行數。
限定:3≤行數N≤100,3≤列數M≤20,1≤鐳射照射次數K≤M。
提示:
電路板可以使用0/1矩陣表示,0表示不導通態,1表示導通態。
輸入:N行×M列的0/1矩陣,及列反轉次數K。求經過K次列反轉後行全為1的最大行數。其中:3≤N≤100,3≤M≤20,1≤K≤M。必須反轉K次,同一列可以多次反轉。
例如,輸入是下圖所示的0/1矩陣,k=3。
1 0 0 1 0
1 1 0 0 0
0 1 1 1 0
0 0 0 1 1
1 0 1 0 1
1 1 0 0 0
輸出:2,即反轉3列,得到最多2行導通。
考慮K的奇偶性及一行中0的個數的奇偶性。最終變為排序問題。
實現程式碼:
/*測試環境:VS2017*/ #include<iostream> #include<math.h> using namespace std; int M,N,k; int **a,**b,*num_0,*odd,*even,*com; int MaxCount=0,num=0; void GetData()//依據輸入確定M和N的大小,並讀入資料 { cout << "請依次輸入行數N、列數M、鐳射照射次數k(3≤N≤100,3≤M≤20,1<=k<=M):"; cin >> N >> M>>k; a = new int*[N]; b = new int*[N]; for (int i = 0; i < N; i++) { a[i] = new int[M]; b[i] = new int[M]; } cout << "請輸入資料陣列:"<<endl; for(int i=0;i<N;i++) for (int j = 0; j < M; j++) { cin >> a[i][j]; b[i][j] = a[i][j]; } } inline void Trans(int **arr,int m)//列反轉 { int n = N; while (n--) arr[n][m] = abs(arr[n][m] - 1); } int Judge(int **arr)//計算導通行數 { int count=0; for (int i = 0; i < N; i++) { bool L = true; for (int j = 0; j < M; j++) { if (arr[i][j] == 0) { L = false; break; } } if(L) count++; } return count; } void selectSort(int*arr,int len) { int index,temp; for (int i = 0; i < len - 1; i++) { temp = arr[i]; index = i; for (int j = i + 1; j < len; j++) { if (arr[j] < arr[index]) index = j; } arr[i] = arr[index]; arr[index] = temp; } } void Count(int**arr)//計數每行0的個數存在num_0裡,0的個數為偶數且小於k的存於even,類似的奇數存於odd裡 { num_0 = new int[N]; odd = new int[N]; even = new int[N]; com = new int[N]; int count0 = 0, count1 = 0; for (int i = 0; i < N; i++) { int temp=0; for (int j = 0; j < M; j++) if (arr[i][j] == 0) temp++; num_0[i] = temp; } for (int i = 0; i < N; i++) { if (num_0[i] <= k && num_0[i] % 2 == 0) even[count0++] = num_0[i]; if (num_0[i] <= k && num_0[i] % 2 == 1) odd[count1++] = num_0[i]; } selectSort(even, count0 ); selectSort(odd, count1 ); if (k % 2 == 0) { for (int i = 0; i < count0; i++) com[i] = even[i]; num = count0; } if (k % 2 == 1) { for (int i = 0; i < count1; i++) com[i] = odd[i]; num = count1; } } void GetResult() { for(int i=0;i<num;i++) for (int j = 0; j < N; j++) { if (com[i] == num_0[j]) { for (int n = 0; n < N; n++) for (int m = 0; m < M; m++) b[n][m] = a[n][m]; for(int m=0;m<M;m++) if (b[j][m] == 0) Trans(b, m); } MaxCount = (MaxCount >= Judge(b) ? MaxCount : Judge(b)); } cout << "最大導通數為:" << MaxCount << endl; } int main() { GetData(); Count(a); GetResult(); system("pause"); }
注:程式碼中的排序並不是必要的,不排序也能直接實現;另一種方法是把篩選後的每一行都轉換成十進位制後再排序,找出相等的數的最大個數即為最大導通數。