簡體   English   中英

用 1 和 0 填充矩陣以滿足給定的行和列總和的程序

[英]Program to fill a matrix with 1s and 0s to such that it satisfies the given row and column sums

我應該編寫一個程序,用 0 和 1 填充矩陣( flag[][] ,這里),以滿足給定的行和列總和。 行和列總和將通過添加a[][]元素的小數部分來計算。 我寫了下面給出的代碼,當我只運行它的這部分時它可以工作:

#include<stdio.h>
#include<stdlib.h>
    
int main()
{int m=3;
 int flag[3][3];
 int rSum[] = {1,1,2};
 int cSum[] = {2,1,1};
for(int i=0;i<m;i++)
{int k = 0;
    for(int j=0;j<rSum[i];j++)
    {
        if(cSum[k] == 0)
        {
            j--;
            k++;
        }
        else
        {  
            flag[i][k] = 1;
            cSum[k]--;
            k++;
        }
    }
}
return 0;
}

但是整個代碼在運行時給出了錯誤的輸出。 整個代碼:

 #include<stdio.h>
 #include<stdlib.h>

 int main()
{
printf("Enter the size of matrix: ");
int m,n;
scanf("%d %d",&m,&n);
float a[m][n];

printf("Enter the elements: ");
for(int i=0;i<m;i++)
{
    for(int j=0;j<n;j++)
    {
        scanf("%f",&a[i][j]);
    }
}

float b[m][n];
for(int i=0;i<m;i++)
{
    for(int j=0;j<n;j++)
    {
        b[i][j] = a[i][j] - (int)a[i][j];
        printf("%f ",b[i][j]);  
    }
    printf("\n");
}
printf("\n\n\n");
float rSum[m], cSum[n];
for(int i=0;i<n;i++)
{
    cSum[i] = 0;
}
for(int i=0;i<m;i++)
{
    rSum[i] = 0;
}

for(int i=0;i<m;i++)
{
    for(int j=0;j<n;j++)
    {
        rSum[i] += b[i][j];
    }

}

for(int i=0;i<n;i++)
{
    for(int j=0;j<m;j++)
    {
        cSum[i] += b[j][i];
    }

}
printf("\nrSum:");
for(int i=0;i<m;i++)
{
    printf("%f ",rSum[i]);
}
printf("\ncSum:");
for(int i=0;i<n;i++)
{
    printf("%f ",cSum[i]);
}
    
int flag[m][n];

for(int i=0;i<m;i++)
{
    for(int j=0;j<n;j++)
    {
        flag[i][j] = 0;
    }
}

for(int i=0;i<m;i++)
{int k = 0;
    for(int j=0;j<rSum[i];j++)
    {
        if(cSum[k] == 0)
        {
            
            j--;
            k++;
        }
        else
        {    
            flag[i][k] = 1;
            cSum[k]--;
            k++;
        }
    }
}   
printf("\n\n\n");
for(int i=0;i<n;i++)
{
    for(int j=0;j<m;j++)
    {
        printf("%d ",flag[i][j]);
    }
    printf("\n");
}
return 0;
}

任何人都可以指出我犯的錯誤嗎? 為什么第一個代碼可以正常工作,而第二個代碼不行? 另外,我對a[][]輸入是{1.2 , 3.4, 2.4, 3.9, 4.0, 2.1, 7.9, 5.6, 0.5}

在您的程序中,您有一個在許多部分反復犯的大錯誤:不要將float類型變量視為int

首先,您不應該將 ( == ) float與任何數字進行比較。 所以cSum[k] == 0是錯誤的。 相反,您應該指定一個閾值並比較數字和閾值之間的距離。

所以改變這一行

if(cSum[k] == 0)

if (fabsf(cSum[k]) < epsilon) // You can set epsilon to 0.0005

其中epsilon是一個非常小的數字(即float型),可以用作閾值。

另外, cSum[k] -= 1.0f; cSum[k]--;好得多cSum[k]--; 這不一定是錯誤的,但您應該告訴閱讀您的代碼的人cSum[k]是一個float

最后,改變這一行

for(int j=0;j<rSum[i];j++)

for(int j=0;j<round(rSum[i]);j++)

我給你舉個例子。 認為

j = 2  rSum[i] = 2.00000000000000009

你對j < rSum[i]什么j < rSum[i]

事實上,我們希望它們彼此相等,但由於浮點數的精度問題,它們並不相等。 檢查j < rSum[i]得出的結論是rSum[i]大於j 但這是錯誤的。 所以我們應該強迫他們平等。 因此,您可以使用round函數來防止這種情況。 你會得到

j = 2  rSum[i] = 2.00000000000000000

您可以在此處找到更多信息

簡而言之,在您的程序中,由於比較沒有成功,所以需要iffor部分。

僅更改此部分並添加( #include <math.h> ):

float epsilon = 0.0005f;
for(int i=0;i<m;i++)
{int k = 0;
    for(int j=0;j<round(rSum[i]);j++)
    {
        if(fabsf(cSum[k]) <epsilon)
        {
            j--;
            k++;
        }
        else
        {
            flag[i][k] = 1;
            cSum[k] -= 1.0f;
            k++;
        }
    }
}

之后,您將按預期找到輸出:

1 0 0 
1 0 0
0 1 1

問題

首先,我沒有看到您將矩陣設置為 0 的位置。如果您已經收到一個每個數字都為 0 的矩陣,請指定。

但我也認為您的邏輯通常無法解決給定的問題。 您正在使用一種貪婪的策略,該策略在當前可能的情況下放置一個數字。 但是您不能保證這對於最終解決方案是正確的。

例子

假設您有以下矩陣:

1 0 0 - 1  
0 0 1 - 1  
1 0 1 - 2  
| | |  
2 0 2

如您所見,行的總和為 {1, 1, 2},列的總和為 {2, 0, 2}。 現在您的算法將正確地將 1 放在flag[0][0]然后,當該行完成時,它將移動到下一行。
這里它將在第一列( flag[1][0] )中放置一個 1,因為列總和仍然允許它,行總和也是如此。 現在我們再次移動到下一行,完成了第二行的總和。
第一列已經滿了,所以我們給它留 0。下一列只能有 0,因為它的總和是 0。所以我們只剩下第三列,我們在那里放了一個 1。但是現在我們的最終矩陣flag如下所示:

1 0 0  
1 0 0  
0 0 1  

這顯然是一個錯誤的答案。

可能的解決方案

我建議嘗試使用回溯來解決這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM