因为每个人只能选一次,所以枚举状态的时候从大到小。
读入数据比较麻烦,可以用istringstream 或sscanf 或自己写个函数逐个字符处理。
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<sstream> #include<cmath> #include<climits> #include<string> #include<map> #include<queue> #include<vector> #include<stack> #include<set> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define pb(a) push_back(a) #define INF 0x1f1f1f1f #define lson idx<<1,l,mid #define rson idx<<1|1,mid+1,r #define PI 3.1415926535898 template<class T> T min(const T& a,const T& b,const T& c) { return min(min(a,b),min(a,c)); } template<class T> T max(const T& a,const T& b,const T& c) { return max(max(a,b),max(a,c)); } void debug() { #ifdef ONLINE_JUDGE #else freopen("d:\in.txt","r",stdin); freopen("d:\out1.txt","w",stdout); #endif } int getch() { int ch; while((ch=getchar())!=EOF) { if(ch!=' '&&ch!=' ')return ch; } return EOF; } int p3[10]; int init() { p3[0]=1; for(int i=1;i<=8;i++) p3[i]=p3[i-1]*3; return 0; } int n,m,s; int dp[7000]; int da[110][10]; int val[110]; int main() { // freopen("d:\in.txt","r",stdin); init(); while(cin>>s>>m>>n&&s) { int ans[10]={0}; int sum=0; string str; getline(cin,str); for(int i=1;i<=m;i++) { getline(cin,str); // cout<<str<<endl; istringstream in(str); int x; in>>x; sum+=x; while(in>>x) { ans[x-1]++; } } int ST=0; for(int i=0;i<s;i++) { ST+=p3[i]*(ans[i]>2?2:ans[i]); } memset(dp,INF,sizeof(dp)); dp[ST]=sum; memset(da,0,sizeof(da)); for(int i=1;i<=n;i++) { getline(cin,str); istringstream in(str); in>>val[i];; int x; while(in>>x) { da[i][x-1]=1; } } int total=p3[s]-1; for(int i=1;i<=n;i++) { for(int st=total;st>=ST;st--) { int nst=st; int ans[10]; for(int j=0,k=st;j<s;j++) { ans[j]=k%3; k/=3; } for(int j=0;j<s;j++) { if(da[i][j]&&ans[j]<2) nst+=p3[j]; } dp[nst]=min(dp[nst],dp[st]+val[i]); } } cout<<dp[total]<<endl; } return 0; }