不是 AI……
只 AC 了 #1~7 和 #20
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=15;
const int M=1e5+5;
const int Max_of_plans=(1<<15)+10;
int n,m;
const int INF=1e18+9;
int a[N][M];
//在深度为i的地铁站j建地铁的花费
int cost_of_build[N][M];
//在深度为i的地方建地铁线j的花费
bool can_build_at_the_same_depth[N][N];
int c[N];
int cross[N][M];
//地铁线i所经过的第j个地铁站
int iscross[N];
//地铁线i所经过的地铁站(二进制)
int cost_depth_plans[N][Max_of_plans];
//表示在深度为i时建设地铁状态为s的话费
int have_already_built[N];
//表示已经在建了地铁了
int dp[N][Max_of_plans];
int lowbit(int x){
return x&(-x);
}
signed main(){
cin>>n>>m;
int cnt_all_plans=(1<<n)-1;
// cout<<"step 1\n";
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
// printf("a[%lld][%lld]=%lld\n",i,j,a[i][j]);
can_build_at_the_same_depth[i][j]=true;
}
}
// cout<<"step 2\n";
//
//
// cout<<"step 3\n";
for(int i=1;i<=n;i++){
cin>>c[i];
for(int j=1;j<=c[i];j++){
cin>>cross[i][j];
iscross[i]|=(1ll<<(cross[i][j]-1ll));
for(int k=1;k<=n;k++){
//在深度为i的地方,线路j在站点cross[j][k]建地铁站的花费
cost_of_build[i][k]+=a[k][cross[i][j]];
}
}
}
// for(int d=1;d<=n;d++){
// for(int i=1;i<=n;i++){
// cout<<"line "<<d<<" build at depth "<<i<<" will cost "<<cost_of_build[i][d]<<"\n";
// }
// }
// cout<<"step 4\n";
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if((iscross[i]&iscross[j])==0){
can_build_at_the_same_depth[i][j]=true;
}else{
can_build_at_the_same_depth[i][j]=false;
}
}
}
// for(int i=1;i<=n;i++){
// for(int j=1;j<=n;j++){
// printf("For line %d and %d %d\n",i,j,can_build_at_the_same_depth[i][j]);
// }
// }
// cout<<"step 5\n";
for(int i=0;i<=cnt_all_plans;i++){
// printf("----------------case %lld:---------------\n",i);
int cnt_of_have_already_built=0;
for(int j=1;j<=n;j++){
// cout<<(i&(1<<(j-1)))<<"\n";
if((i&(1<<(j-1)))==0) continue;
int now_judge=j;
// cout<<i<<"now judge:"<<now_judge<<"\n";
cnt_of_have_already_built++;
have_already_built[cnt_of_have_already_built]=now_judge;
for(int k=1;k<cnt_of_have_already_built;k++){
// cout<<have_already_built[k]<<" ";
if(!can_build_at_the_same_depth[now_judge][have_already_built[k]]){
// cout<<"For case "<<i<<" : line "<<now_judge<<" and line "<<have_already_built[k]<<" can't build\n";
// cout<<i<<"is unaccepted!\n";
for(int d=1;d<=n;d++){
cost_depth_plans[d][i]=INF;
}
}
}
if(cost_depth_plans[1][i]==INF){
break;
}
for(int d=1;d<=n;d++){
cost_depth_plans[d][i]+=cost_of_build[now_judge][d];
}
}
}
// for(int i=1;i<=n;i++){
// for(int j=0;j<=cnt_all_plans;j++){
// printf("For depth %d and case %d :%d \n",i,j,cost_depth_plans[i][j]);
// }
// }
// cout<<"step \n";
for(int i=0;i<=cnt_all_plans;i++){
dp[1][i]=cost_depth_plans[1][i];
}
for(int i=2;i<=n;i++){
for(int s=0;s<=cnt_all_plans;s++){
dp[i][s]=INF;
for(int son=s;son;son=(son-1)&s){
if(dp[i-1][s^son]==INF) continue;
dp[i][s]=min(dp[i][s],dp[i-1][s^son]+cost_depth_plans[i][son]);
}
}
}
// cout<<"step \n";
cout<<dp[n][cnt_all_plans]<<'\n';
}