列舉(矩陣消除、七段數碼管)

AC_no error發表於2020-10-22

目錄

 

矩陣消除:

題目:

思路:

程式碼:

七段數碼管(藍橋杯題目)

大致題意:

思路:

 程式碼:


矩陣消除:

題目:

牛妹在玩一個名為矩陣消除的遊戲,矩陣的大小是行列,第行第列的單元格的權值為,

牛妹可以進行個回合的遊戲,在每個回合,牛妹可以選擇一行或者選擇一列,

然後將這一行或者這一列的所有單元格中的權值變為,同時牛妹的分數會加上這一行或者這一列中的所有單元格的權值的和。

牛妹想最大化她的得分,球球你幫幫她吧!

輸入描述:

第一行三個整數

接下來行每行個整數表示矩陣中各個單元格的權值。

輸出描述:

輸出一個整數表示牛妹能獲得的最大分數。

1<=n,m<=15 1<=k<=n*m

思路:

         剛開始想著記錄每行每列的數,排序,選擇,重排。顯然,會造成相等情況下不同選擇會有不同的結果。這個思路可以pass掉了。

         資料範圍較小的時候,用二進位制列舉:利用二進位制列舉每一種狀態。比如010101,就是選擇1 3 5不選擇2 4 6。在這裡列舉那幾行,然後重新排列再選擇最高的幾列(選擇列的時候不會改變其它列的和)。

         列舉行數比k大或者列舉的行數+所有列數都達不到k,就沒有必要再算下去,直接continue;

         K的值是≤n*m,需要縮小k的範圍,賦值k,n,m的最小的那一樣數(如果n,m小,k直接全部選擇即可)

程式碼:

#include<algorithm>

#include<iostream>

#include<cstring>

#include<string>

#include<cstdlib>

#include<map>

#include<cmath>

#include<vector>



using namespace std;

typedef long long ll;

const int maxn = 1e6+50;

ll _map[20][20];

int main(){

         int n,m,k;

         cin >> n >> m >> k;

         ll ans = 0,sum_x[20]={0};

         for(int i = 1;i <= n;i++){

                  for(int j = 1;j <= m;j++)

                          cin >> _map[i][j],sum_x[i]+=_map[i][j];

         }

         k=min(k,n);k=min(k,m);

         int sta = (1<<n);

         for(int i = 0;i < sta;i++){

                  ll sum_y[20] = {0},maxs = 0,cnt_c=0;

                  for(int j = 1;j <= m;j++)

                          for(int k = 1;k <= n;k++)

                                   sum_y[j]+=_map[k][j];

                  for(int j = 0;j < n;j++){

                          if(((i>>j)&1)){

                                   cnt_c++;

                                   maxs += sum_x[j+1];

                                   for(int k = 1;k <= m;k++)

                                            sum_y[k]-=_map[j+1][k];

                          }

                  }

                  if(cnt_c+m < k||cnt_c > k)    continue;/*k<=n*m  過大的話可能導致cnt_c+m<k退出,極限等於min(m,n,k)即可*

                  sort(sum_y+1,sum_y+m+1);

                  if(cnt_c < k)

                          for(int j = m;j >= 1;j--){

                                   maxs+=sum_y[j];

                                   if(cnt_c+(m-j+1) == k) break;//錯誤 需要判斷不需要列的情況

                          }               

                  ans = max(ans,maxs);

         }

         cout << ans << endl;

}

七段數碼管(藍橋杯題目)

大致題意:

七條邊,不能全滅,有的亮有的滅或者全亮。所有亮的並且連通的種類數。

思路:

並查集+dfs,我感覺比較複雜,不如列舉每一種情況(畢竟只有7個管),然後判斷是否

連通(可以利用Flody,離散中的沃舍爾演算法)。

 程式碼:

#include<algorithm>

#include<iostream>

#include<cstring>

#include<string>

#include<queue>

#include<map>

#include<cstdio>

#include<cmath>

#include<stdlib.h>



using namespace std;

typedef long long ll;

const int INF = 0x3f3f3f3f;

const int maxn = 1e6+50;

int dis[10][10];

int a[10];

int tot;

void ini(){

         dis[1][1] = 0;     

         dis[1][2] = 1;      dis[2][2]=0;

         dis[1][3] = INF;dis[2][3]=1;  dis[3][3]=0; 

         dis[1][4] = INF;dis[2][4]=INF;dis[3][4]=1;     dis[4][4]=0; 

         dis[1][5] = INF;dis[2][5]=INF;dis[3][5]=INF;dis[4][5]=1;  dis[5][5]=0;

         dis[1][6] = 1;      dis[2][6]=INF;dis[3][6]=INF;dis[4][6]=INF;dis[5][6]=1;dis[6][6]=0;

         dis[1][7] = INF;dis[2][7]=1;  dis[3][7]=1;  dis[4][7]=INF;dis[5][7]=1;dis[6][7]=1;dis[7][7]=0;

         for(int i = 1;i <= 7;i++)

                  for(int j = i;j <= 7;j++)

                          dis[j][i] = dis[i][j];

}

void Floyd(){

         for(int k = 0;k < tot;k++)

                  for(int i = 0;i < tot;i++)

                          for(int j = 0;j < tot;j++)

                                   if(dis[a[i]][a[j]] > dis[a[i]][a[k]]+dis[a[k]][a[j]])

                                            dis[a[i]][a[j]] = dis[a[i]][a[k]]+dis[a[k]][a[j]];

}

bool check(int sta){

         int cnt = 1;tot = 0;

         while(sta){

                  if(sta&1==1)      a[tot++]=cnt;

                  sta>>=1;

                  cnt++;

         }

         Floyd();

         for(int i = 0;i < tot;i++)

                  for(int j = 0;j < tot;j++)

                          if(dis[a[i]][a[j]] == INF) return false;

         return true;

}

int main(){

         int sta = 1<<7,cnt=0;

         for(int i = 1;i < sta;i++){

                          ini();

                          if(check(i)) cnt++;

         }

         cout<<cnt<<endl;

         return 0;

}

 

相關文章