目录
矩阵消除:
题目:
牛妹在玩一个名为矩阵消除的游戏,矩阵的大小是行列,第行第列的单元格的权值为,
牛妹可以进行个回合的游戏,在每个回合,牛妹可以选择一行或者选择一列,
然后将这一行或者这一列的所有单元格中的权值变为,同时牛妹的分数会加上这一行或者这一列中的所有单元格的权值的和。
牛妹想最大化她的得分,球球你帮帮她吧!
输入描述:
第一行三个整数
接下来行每行个整数表示矩阵中各个单元格的权值。
输出描述:
输出一个整数表示牛妹能获得的最大分数。
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;
}