普及状压选做
目录
- 第1题
- 第2题
- 第3题
- 第4题
- 第5题
- 第6题
第1题
看了题解。
把点 \(n\) 作为不存在的第二起始点真是惊为天人的操作。(其实是我太菜啦)
#include
using namespace std;
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
const int N = 13;
int n,m,v[N],g[N+1][N+1];
pairf[1<>q;while(q--) {
memset(g,0,sizeof g);
scanf("%d%d", &n,&m);
rep(i,0,n-1)scanf("%d",&v[i]);
rep(i,1,m) {int a,b; scanf("%d%d", &a,&b);
--a;--b; g[a][b] = g[b][a] = 1;
}
memset(f,0x80,sizeof f);
rep(i,0,n-1) f[1< ans = make_pair(0,0);
rep(S,0,(1<>i)&1)) continue;
int Si = S^(1<>j)&1)) continue;
int Sij = Si^(1<>k)&1)) continue;
int tmp = f[Si][j][k].first + v[i]*v[j] + (g[i][k]?v[i]*v[j]*v[k]:0);
if(f[S][i][j].first < tmp) {
f[S][i][j] = make_pair(tmp, f[Si][j][k].second);
} else if(f[S][i][j].first == tmp) {
f[S][i][j].second += f[Si][j][k].second;
}
}
}
}
}
rep(i,0,n-1)rep(j,0,n-1) {
if(ans.first
第2题
似乎是轮廓线的状压
先上乘法原理, 每行的状态用 \(\{ 0,1 \}\) 表示, \(1\) 表示一个竖着的骨牌的上端, 其余为 \(0\)。
转移似乎很难想啊……但发现一次转移无非考虑在本行怎么摆竖骨牌的上端。
配合预处理大法复杂度减少一个 \(O(n)\), 开心食用。
最后复杂度是 \(O(n*2^{m+1})\)
#include
using namespace std;
#define sub(i,k) for(int i=0;i<(1<<(k));++i)
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
const int N = 11;
int n,m;
long long f[N+1][1<>j)&1) {
if(cnt&1) ok = false;
cnt=0;
} else {
++cnt;
}
}
if(cnt&1) ok = false;
good[i] = ok;
// rep(j,0,m-1) cout<<((i>>j)&1);
// cout<<' '<
第3题
经典题哟。
写了一下午自闭了。
换了个写法20min过啦。
#include
using namespace std;
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
const int N = 100;
const int M = 10;
int n,m,a[N+1];
int cnt, nodes[61], sum[61];
long long f[2][61][61];
int main() {
m = 10;
scanf("%d%d", &n,&m);
rep(i,1,n)rep(j,0,m-1) { char c;cin>>c;if(c=='H')a[i]|=(1<
第4题
题意就是求生成树, 因为最优解一定是原图的一个生成树。
刚开始想了个 sb做法, 妄想把每个点的深度信息塞到状态里, 后来发现这不就是爆搜 =_=。
参考题解, 用分层转移的手法, 转移的时候枚举当前生成树的子集作为最后一层, 然后转移, 注意要把当前集的树高塞进状态里。
转移的时候枚举当前集的子集, 将其作为前一状态。、但是无法保证枚举出来的就是 “最后一层”, 似乎可能会出现比最优解更小的解!但是可以冷静地想一下,由于转移总是合法的(即总是生成树), 所以得到的解一定 \(\ge\) 最优解, 而最优解一定会被找出, 所以正确性可以保证owo。
技巧总结: 二进制数表示集合时枚举某集合的子集的方法。
重大失误总结: 没有认识到极限数据(特别是小数据)对答案的影响。
#include
using namespace std;
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
const int N = 12;
int n,m,g[N][N],trans[1<