这是问题。在游戏中,有一个矩形的硬币网格,正面为= 1,尾部为0。游戏有一个简单的规则:玩家不能翻转单个硬币,而是可以选择一行(或一列),然后同时翻转该行(或该列)中的所有硬币。游戏的目的是找到一种翻转硬币的策略,以使正面硬币的数量最大化。第一个输入值是行>>然后是列>>和硬币
Sample inputs:
5 4
1010
0101
1010
1010
1010 //Sample output of this: 20
5 4
0010
1101
0110
0110
1011 //Sample output of this: 17
我使用计数“ 0”和“ 1”的方法完成了代码,如果大于零,请进行切换。这种方法仅通过了简单的测试用例,但是当通过困难的测试用例时,它失败了,因为在某些情况下需要多次进行提示。我想不出另一种更好的处理方法。
这是我的代码:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
bool ConeIsMore(vector <vector<char> > table, int size, int j) {
int countzero = 0;
int countone = 0;
for (int i = 0; i < size; i++) {
(table[i][j] == '0')?++countzero: ++countone;
}
if (countone >= countzero) {
return true;
}
return false;
}
bool RoneIsMore(vector <vector<char> > table, int size, int i) {
int countzero = 0;
int countone = 0;
for (int j = 0; j < size; j++) {
(table[i][j] == '0') ? ++countzero : ++countone;
}
if (countone >= countzero) {
return true;
}
return false;
}
int main() {
//Initialise row and column
int row;
int column;
while (cin >> row >> column) {
//Initiallise 2D vector
vector <vector<char> > table(row, vector<char>(column));
//get each digit of number and store it into number
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
cin >> table[i][j];
}
}
//check for column
for (int j = 0; j < column; j++) {
if (!ConeIsMore(table, row, j)) {
for (int i = 0; i < row; i++) {
(table[i][j] == '0') ? table[i][j] = '1' : table[i][j] = '0';
}
}
}
//check for row
for (int j = 0; j < row; j++) {
if (!RoneIsMore(table, column, j)) {
for (int i = 0; i < column; i++) {
(table[j][i] == '0') ? table[j][i] = '1' : table[j][i] = '0';
}
}
}
//Count One in the table
int ans = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
(table[i][j] == '1') ? (ans++) : (ans = ans);
}
}
cout << ans << endl;
}
return 0;
}
当我研究测试用例时,我发现有一些要求检查各种时间,这使我感到我的方法不是一个好方法。谁能建议一种更好的处理方式?非常感谢。
以下是比较困难的测试用例:
5 4
0010
1101
0110
0110
1011 //17
5 4
0110
1111
0101
0110
0100 //16
5 4
0110
1001
0011
1110
1000 //16
5 4
1100
0001
1111
0101
1010 //16
5 4
0101
0110
1001
1000
0011 //16
5 4
0111
1100
0100
1000
1011 //16
5 4
1101
1110
0111
1011
0111 //15
5 4
1100
1001
0110
1001
1000 //17
答案 0 :(得分:1)
也许您应该输出策略的结果,而不仅仅是头脑好,以便更好地了解正在发生的事情。改善实施的两个想法:
1)当行或列中的硬币数量为偶数时,您的代码没有执行您所描述的算法。你说:
计算“ 0”和“ 1”,如果大于零,则将其切换。
您的代码可以:
if (!ConeIsMore(table, row, j)) {
// switch it
}
当没有更多的打印头时切换。 结果,当硬币数量为偶数时, 头和尾的数目相等。当计数相等时切换是推测性的,尚不清楚它是否可以改善任何东西,因此您可能应该特别对待它。
2)您也许可以继续迭代直到没有 尾部比头部多的列或行。
std::vector<bool> table(row*column)
的数据结构可能会更高效,但也需要多加注意才能正确处理。
答案 1 :(得分:1)
如果您翻转每一列或每一行,我们需要跟踪总计的头数。对于给定的行或列,如果决定翻转该行或列,请计算尾数减去头数以产生头的净增加。将这些值存储在两个数组中,一个用于列,一个用于行。此时,您应该有两个数组,大小为行的一个,大小为列的一个,其值为负,零或正值。
5 4
1010
0101
1010
1010
1010 //Sample output of this: 20
row: [0, 0, 0, 0, 0]
column: [-3, 3, -3, 3]
现在遍历行和列向量,如果遇到正值,则需要翻转该行或列。如果遇到负值,请勿翻转。 如果遇到零值,则应根据该行或该列的第一个硬币是否已经是正面硬币的决定来决定翻转。这将有助于解决以下情况: / p>
2 2
10
01 // output should be: 4
row: [0, 0] // How can we know to flip row 1 but not row 0? Because arr[0][0] = 1 already
column: [0, 0]
您必须采取的另一步骤是,当您翻转一行时,还必须更新列数组中的值,反之亦然。您还应该更新内存中的2d硬币阵列以反映新状态。第一次翻转后,问题状态看起来像这样
5 4
1010
1010 // this row was flipped because arr[1][0] was 0
1010
1010
1010
row: [0, 0, 0, 0, 0]
column: [-5, 5, -5, 5]
继续,直到没有更多的行或列可以翻转。在实现中有一个很好的递归机会。
答案 2 :(得分:0)
以下是在Peter Cheng帮助提供该算法之后的代码。它可以一直工作到计算行和列,但是无法翻转表格。
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int RcountDifference(vector <vector<char> > table, int col, int var) {
int Difference = 0;
for (int j = 0; j < col; j++) {
if (table[var][j]=='1') {
Difference -= 1;
}
else {
Difference += 1;
}
}
return Difference;
}
int CcountDifference(vector <vector<char> > table, int row, int var) {
int Difference = 0;
for (int i = 0; i < row; i++) {
if (table[i][var] == '1') {
Difference -= 1;
}
else {
Difference += 1;
}
}
return Difference;
}
int main() {
//Initialise row and column
int r;
int c;
while (cin >> r >> c) {
//Initiallise 2D vector
vector <vector<char> > table(r, vector<char>(c));
//get each digit of number and store it into number
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cin >> table[i][j];
}
}
//Build two arrays to store the value "zero-one"
vector <int> row;
vector <int> column;
//store for vector
//For Row
for (int i = 0; i < r; i++) {
row.push_back(RcountDifference(table, c, i));
}
//For Column
for (int j = 0; j < c; j++) {
column.push_back(CcountDifference(table, r, j));
}
Flip(r, c, table, row, column);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
//Flip for row
if (row[i]>0) {
(table[i][j] == '0') ? '1' : '0';
}
else if (row[i] == 0 && table[i][0]=='0') {
(table[i][j] == '0') ? '1' : '0';
}
else {
(table[i][j] == '0') ? '0' : '1';
}
row.clear();
row.push_back(RcountDifference(table, c, i));
column.clear();
column.push_back(CcountDifference(table, r, j));
//Flip for column
if (column[j] > 0) {
(table[i][j] == '0') ? '1' : '0';
}
else if (column[j] == 0 && table[0][j] == '0') {
(table[i][j] == '0') ? '1' : '0';
}
else {
(table[i][j] == '0') ? '0' : '1';
}
row.clear();
row.push_back(RcountDifference(table, c, i));
column.clear();
column.push_back(CcountDifference(table, r, j));
}
}
//Output Check
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cout << table[i][j];
}
}
}
return 0;
}
完成解决方案后,我也想把它放在这里,对于像我这样刚接触编码的人来说,学习不同的问题会很好。