不得不說,這題目真的贊(๑•̀ㅂ•́)و✧
Solution
容易想到,題意是求 在保證每行每列的最大值仍舊存在的情況下,所需要的最小磚塊數。
考慮貪心,對於一個貢獻更大的量的量,優先取
此處指 實際貢獻 也就是說 如果該行已經被另一個取了,那麼它的貢獻只剩下列
所以策略在於優先選行列最大值相等的點
~~其實博主太弱不會證明 ~~╯︿╰
另外一種做法是模型轉換 然後二分圖匹配
截個圖吧反正我看不懂絕不是不負責任
Code
二分圖匹配 (來自網絡 侵刪)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=150;
int input(){
int f=1,s=0;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9'){s=s*10+c-'0';c=getchar();}
return s*f;
}
int n,m;
int side[N],fron[N];
int Link[N],mp[N][N];
bool vis[N],a[N][N];
ll sum,red;
bool find(int x){
for(int i=1;i<=m;++i)
if(!vis[i] && a[x][i]){
vis[i]=1;if(!Link[i] || find(Link[i])){Link[i]=x;return 1;}
}
return 0;
}
int main(){
n=input();m=input();
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
mp[i][j]=input();if(!mp[i][j])continue;
side[i]=max(side[i],mp[i][j]);
fron[j]=max(fron[j],mp[i][j]);
++red;sum+=mp[i][j];
}
}
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(mp[i][j] && side[i]==fron[j])a[i][j]=1;
for(int i=1;i<=n;++i){memset(vis,0,sizeof(vis));find(i);}
for(int i=1;i<=n;++i)if(side[i])red+=side[i]-1;
for(int i=1;i<=m;++i)if(fron[i] && !Link[i])red+=fron[i]-1;
printf("%lld\n",sum-red);
return 0;
}
貪心僞裝正解
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define oo 2139062143
#define fo(i,x,y) for (register ll i = (x);i <= (y);++ i)
#define fd(i,x,y) for (register ll i = (x);i >= (y);-- i)
using namespace std;
typedef double db;
typedef long long ll;
ll abs(ll x) {return(((x)>=0)?(x):(-(x)));}
ll max(ll x,ll y) {return(((x)>(y))?(x):(y));}
ll min(ll x,ll y) {return(((x)<(y))?(x):(y));}
ll lowbit(ll x) {return((x)&(-x));}
const ll N = 110;
ll a[N][N];
ll mxx[N],mxy[N];
ll bz[N][N];
ll okx[N],oky[N],b[N];
ll n,m,sum,cost;
int main()
{
scanf("%lld%lld", &n, &m);
fo(i,1,n) fo(j,1,m)
{
scanf("%lld", &a[i][j]);
if (a[i][j]) sum += a[i][j];
mxx[i] = max(a[i][j],mxx[i]);
mxy[j] = max(a[i][j],mxy[j]);
}
fo(i,1,n)
{
cost += mxx[i];
bool ok = 0;
fo(j,1,m)
if (!b[j] && a[i][j] && mxy[j] == mxx[i])
{
bz[i][j] = mxx[i],ok = b[j] = 1;
break;
}
if (!ok)
fo(j,1,m)
if (a[i][j] && mxy[j] >= mxx[i])
{
bz[i][j] = mxx[i];
break;
}
}
fo(j,1,m)
if (!b[j])
{
cost += mxy[j];
fo(i,1,n)
{
if (a[i][j] && !bz[i][j] && mxy[j] <= mxx[i])
{
bz[i][j] = mxy[j];
break;
}
}
}
fo(i,1,n) fo(j,1,m)
if (a[i][j] && !bz[i][j]) ++ cost;
printf("%lld", sum - cost);
}