## 2019icpc台北
J
应该是一个很板的状压&bitset题目(但是之前没用过bitset直接T飞)
bitset写法
bitset<505> ss[20];
void solve(){
int n,m; char s;
cin>>n>>m;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
cin >> s;
if(s == '1') ss[i][j] = 1;
else ss[i][j] = 0;
}
}
int ans = 1000;
for(int i=0;i<1<<m;i++){
int num=0; bitset<505> tmp;
for(int j=0;j<m;j++){
if(i&(1<<j)){
num++;
if (num > ans ) break;
tmp |= ss[j];
}
}
if(tmp.count() == n) ans =min(num,ans);
}
if(ans==1000)cout<<-1<<endl;
else cout<<ans<<endl;
}
玄学优化写法
枚举状态之后按位枚举,当前位找到一组在这位有1的就直接看下一位
void solve(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++) {
for(int j=0;j<n;j++){
scanf(" %c",&s);
if(s=='1')
ve[j].push_back(i);
}
}
//sort(ve.begin(),ve.end(),cmp);
int ans = 1000;
for(int i=0;i<1<<m;i++){
int num=0;
for(int j=0;j<m;j++){
if((1<<j)&i) ++num;
if(num>ans)break;
}
if(num>ans)continue; //优化1
for(int l =0;l<n;l++){ //优化2
for(auto j : ve[l]){
if((1<<j)&i) { st[l] = 1;break; }
}
}
bool f=0;
for(int l =0;l<n;l++){
if(!st[l]) f=1;
st[l]=0;
}
if(!f) ans =num;
}
if(ans==1000)cout<<-1<<endl;
else printf("%d\n",ans);
for(int i=0;i<n;i++) ve[i].clear();
}
E
构造
\(1999*(1998+k)-1998*(1999+k) = k\)
第一个数为-1 , 然后将k分到其他1998个数里面