題目鏈接
題目意思:
n*m的數組, 選取兩行,兩行合併成一行,取對應位置上的最大值,然後再取這行的最小值。使這個最小值最大,問這兩行的行號。
每行的數字最多八個,
思路:
看到每行最多八個數, 就要想到二進制位優化。
首先要二分出來最大的數 x ,
對於這個數,我們進行check。
然後對於每一行, 這一行中如果大於 x, 就設爲1, 否則就設爲 0, 這樣每行就可以組成一個數 y 。vis[y] = i;
這個數最大就是256 , 就可以兩重for循環,然後暴力判斷這兩行是不是滿足條件。
判斷的標準就是 if (vis[i] && vis[j] && (i|j) == (1 << m) - 1)
。
反思:
太巧妙了emmmm
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
int a[N][10],n,m,ans1,ans2;
int vis[500];
bool fuck(int x){
int tmp;
memset(vis, 0, sizeof vis);
for (int i = 1; i <= n; ++i){
tmp = 0;
for (int j = 1; j <= m; ++j){
if (a[i][j] >= x) tmp |= (1 << (j - 1));
}
vis[tmp] = i;
}
int mx = 1 << m;
for (int i = 0; i < mx; ++i){
for (int j = 0; j < mx; ++j){
if (vis[i] && vis[j] && (i|j) == (1 << m) - 1) {
ans1 = vis[i], ans2 = vis[j];
return 1;
}
}
}
return 0;
}
int main(){
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
scanf("%d",&a[i][j]);
int l = 0, r = 1e9, mid;
while(l <= r){
mid = (l + r) >> 1;
if (fuck(mid)) l = mid + 1; else r = mid - 1;
}
printf("%d %d\n",ans1, ans2);
return 0;
}