[SNCPC2024] 表达式矩阵 题解
考虑朴素暴力,显然不能有符号相邻或者在边界上。暴力搜小数据答案,发现如果一个位置
但是这样太不优雅了。直接将这些位置先全部填上 *,发现答案不一定最优。考虑把若干个 * 替换成 +,对照打出来的表发现这样的 + 不超过 * 的个数不超过 * 要变成 +,时间复杂度取决于实现。
放代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int g(int x){
int c=0;
while(x--)c=(c<<1)+(c<<3)|1;
return c;
}
inline int f0(string s){
vector<int> t;
for(int i=0,l=0;i<=s.length();i++)
if(i==s.length()||s[i]=='*')
t.emplace_back(i-l),l=i+1;
int c=1;
for(int i:t)c*=g(i);
return c;
} // 计算仅含 * 的表达式的值
inline int f1(string s){
vector<string> t;
for(int i=0,l=0;i<=s.length();i++)
if(i==s.length()||s[i]=='+')
t.emplace_back(s.substr(l,i-l)),l=i+1;
int c=0;
for(auto i:t)c+=f0(i);
return c;
} // 计算表达式的值
inline int f2(vector<string> a){
int c=0;
for(int i=0;i<a.size();i++)
c+=f1(a[i]);
for(int i=0;i<a[0].size();i++){
string s;
for(int j=0;j<a.size();j++)
s+=a[j][i];
c+=f1(s);
}
return c;
} // 计算一个矩阵的答案
main(){
ios::sync_with_stdio(false);
int n,m,r=6e18; cin>>n>>m;
vector<string> a(n,string(m,49)),w;
vector<pair<int,int> > p;
for(int i=1;i<n-1;i++)
for(int j=1;j<m-1;j++)
if(!(i+j&1))a[i][j]='*',p.emplace_back(i,j);
for(int i=0;i<1<<p.size();i++)
if(__builtin_popcount(i)<6){
auto b=a;
for(int j=0;j<p.size();j++)
if(i>>j&1)b[p[j].first][p[j].second]='+';
if(int x=f2(b);x<r)r=x,w=b;
} // 暴力枚举
for(auto i:w)cout<<i<<'\n';
return 0;
}