250
PointyWizardHats
题意:n个圆锥型小帽子和m个圆锥形大帽子,现在要把一顶小帽子和一顶大帽子组合起来,组合的条件是xxx,问最多能组合多少对
分析:直白的二分图匹配,少见250出这个
600
MagicalHats
题意:一块13*13的板子,一些位置有帽子,某些帽子后面藏有面值不同的硬币,且任意时刻每个帽子后面只有至多一枚硬币,现在要猜K次,魔术师在每次猜之前可以改变硬币所属的帽子(被猜过的地方就不能改了),并且保证任意时刻每行每列帽子数和硬币数的奇偶性相同,你的目标是最大化得到的硬币价值,魔术师的目标,保证最多有13顶帽子
分析:3进制压一下状态,预处理出每个状态是否合法,记忆化搜索一下
950
CosmicBlocks
题意:有6种颜色的砖块,每种有若干个(<=7500),现在要把这些所有砖块搭起来,要求相同颜色的砖块高度相同;定义两种本质不同的方案当且仅当在一种方案中存在一个颜色的砖块在另一个颜色的下面,而在第二种方案中不存在这对颜色,问有多少种方案的拓扑排序种数在[L,R]
分析:因为颜色数只有6,可以爆搜所有方案,判断一下合不合法,判断的时候需要用网络流。不过有一种 2n 枚举行看和是否够的方法可以过,可能是数据问题
class CosmicBlocks {
public:
vector<int>V;
int minWays,maxWays;
int ans;
int n;
int ned[11];
int cnt[8];
int bel[11];
int tot;//maxH+1
vector<int>G[11];//edge
vector<int>has[11];//v in hi
int fa[7];
int occ[7];
int dp[(1<<6)+3];
bool check(){
for(int i=1;i<tot;i++){
vector<int>tmpV=V;
for(int j=0;j<has[i].size();j++){
int u=has[i][j];
for(int it=0;it<G[u].size();it++){
int v=G[u][it];
tmpV[v]--;
tmpV[u]--;
}
}
for(int j=0;j<n;j++)if(tmpV[j]<0)return 0;
for(int mask=0;mask<1<<has[i].size();mask++){
memset(occ,0,sizeof(occ));
int nedcost=0,hascost=0;
for(int j=0;j<has[i].size();j++){
if(mask>>j&1){
int u=has[i][j];
nedcost+=tmpV[u];
for(int k=0;k<G[u].size();k++){
if(!occ[G[u][k]]){
occ[G[u][k]]=1;
hascost+=tmpV[G[u][k]];
}
}
}
}
if(nedcost>hascost)return 0;
}
}
memset(dp,0,sizeof(dp));
memset(fa,0,sizeof(fa));
dp[0]=1;
for(int i=0;i<n;i++){
for(int j=0;j<G[i].size();j++){
fa[G[i][j]]|=(1<<i);
}
}
for(int mask=0;mask<1<<n;mask++){
for(int i=0;i<n;i++){
if(mask>>i&1)continue;
if((mask|fa[i])!=mask)continue;
dp[mask|(1<<i)]+=dp[mask];
}
}
//printf("dp=%d\n",dp[(1<<n)-1]);
return dp[(1<<n)-1]>=minWays&&dp[(1<<n)-1]<=maxWays;
}
void dfs3(int cur){
if(cur>=n){
/*
puts("haaha");
for(int i=0;i<n;i++){
printf("%d: ",i);
for(int j=0;j<G[i].size();j++){
printf("%d ",G[i][j]);
}
puts("");
}
*/
if(check())ans++;
return;
}
int h=bel[cur];
if(!h){G[cur].clear();dfs3(cur+1);}
else{
int bef=(int)has[h-1].size();
for(int mask=1;mask<1<<bef;mask++){
G[cur].clear();
for(int j=0;j<bef;j++){
if(mask>>j&1){
G[cur].push_back(has[h-1][j]);
}
}
dfs3(cur+1);
}
}
}
void dfs2(int cur){
if(cur>=n){
for(int i=0;i<tot;i++)has[i].clear();
for(int i=0;i<n;i++)has[bel[i]].push_back(i);
//for(int i=0;i<n;i++)printf("%d ",bel[i]);puts("");
dfs3(0);
//printf("tmpans=%d\n",ans);
//exit(0);
return;
}
for(int i=0;i<tot;i++){
if(cnt[i]<ned[i]){
cnt[i]++;
bel[cur]=i;
dfs2(cur+1);
cnt[i]--;
}
}
}
void dfs1(int cur,int rest){
if(!rest){
memset(cnt,0,sizeof(cnt));
tot=cur;
//for(int i=0;i<tot;i++){printf("%d ",ned[i]);}puts("");
dfs2(0);
//printf("ans=%d\n",ans);
//exit(0);
return;
}
for(int i=1;i<=rest;i++){
ned[cur]=i;
dfs1(cur+1,rest-i);
}
}
int getNumOrders(vector<int> blockTypes, int minWays, int maxWays) {
V=blockTypes;
this->minWays=minWays;
this->maxWays=maxWays;
n=blockTypes.size();
ans=0;
dfs1(0,n);
return ans;
return 0;
}
};