谈一下自己对dp的想法。
dp的感觉就分两种 1.模拟,根着题目的意思一个个选择(dfs);就像本题一个个选择老师;
2.大化小,紫书习题3 切蛋糕,和习题4 flod 字符串,就好。
dp的状态,就像函数里的自变量,dp的值就像函数的自变量。
剩下的紫书就讲的很详细了
//uva 10817
//紫书 第9章 例15
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<sstream>
#include<cstring>
#include<string>
using namespace std;
const int maxn=100+25;
const int inf =0x3f3f3f3f;
int p[maxn];
int ret[maxn];
int s,n,m;
int N;
int dp[1<<10][1<<10][maxn];
int dfs(int s0,int s1,int s2,int pos)
{
if(pos==N)
{
return s2==(1<<s)-1 ? 0:inf;
}
if(dp[s1][s2][pos]!=-1)
{
return dp[s1][s2][pos];
}
dp[s1][s2][pos]=inf;
if(pos>=m)
dp[s1][s2][pos]=dfs(s0,s1,s2,pos+1);
//if(pos>=m)
//
int m0,m1;
m0=s0&ret[pos];
m1=s1&ret[pos];
int t0,t1,t2;
t0=s0^m0;
t1=s1^m1|m0; /*akfjcasjk*/
t2=s2|m1;
dp[s1][s2][pos]=min(dp[s1][s2][pos],dfs(t0,t1,t2,pos+1)+p[pos]);
//}
return dp[s1][s2][pos];
}
int main()
{
string str;
// printf("%d\n",inf);
while(scanf("%d",&s)!=EOF)
{
if(s==0) break;
scanf("%d %d",&m,&n);
if(s==0 && m==0 && n==0) break;
N=n+m;
for(int i=0;i<N;i++)
{
//re[i].clear();
scanf("%d",&p[i]);
getline(cin,str);
stringstream s(str);
int t;
ret[i]=0;
while(s>>t)
{
t--;
ret[i]=ret[i]|(1<<t);
}
//cout<<ret[i]<<endl;
}
// for(int i=0;i<n+m;i++)
// {
// for(int j=0;j<re[i].size();j++)
// {
// cout<<re[i][j]<<" ";
// }
// cout<<endl;
// }
memset(dp,-1,sizeof(dp));
int ans=dfs((1<<s)-1,0,0,0);
printf("%d\n",ans);
// cout<<m<<n<<endl;
}
return 0;
}
//很经典的一题