URAL 1326. Bottle Taps


   动态规划,求出可以达到的所有状态。然后枚举所有可以达到的状态求最小值。

每个offer用一个int 存。dp的话,用滚动数组。节省空间。


#define FOR(i,n) for(long long (i)=1;(i)<=(n);(i)++)
#define For(i,n) for(long long (i)=0;(i)<(n);(i)++)
using namespace std;

int dp[2][1048576];
int N,M;
int price[20];//20个单价 
int Want[20];//需要的物品编号。 
int Wn;//需要的物品数量 
int Mark[100];//100个集合的情况 
int Mprice[100];//100个集合的状态 
int main(void)
{
	while(cin>>N){
		For(i,N) scanf("%d",&price[i]),Want[i]=0;
		cin>>M;Wn=0;
		int n,a;
		For(i,M){
			Mark[i]=0;
			scanf("%d%d",&Mprice[i],&n);
			For(j,n){
				scanf("%d",&a);
				Mark[i]|=1<<(a-1);
			}
			
		}
		scanf("%d",&n);
		For(j,n){
			scanf("%d",&a);
			Want[Wn++]=a-1;
		}
		memset(dp,-1,sizeof(dp));
		int ANS=inf;
		if(M>0){
			//DP 
			dp[0][0]=0;
			For(i,M){
				int I=i&1,IN=~i&1;//提前存下来,比直接写在表达式里,快了0.1秒左右。 
				For(j,1<<N) dp[IN][j]=-1;
				For(j,1<<N){
					if(~dp[I][j]){
						int J=j|Mark[i],D=dp[I][j]+Mprice[i];
						if(!~dp[IN][j]||dp[IN][j]>dp[I][j]) dp[IN][j]=dp[I][j];
						if(!~dp[IN][J]||dp[IN][J]>D) dp[IN][J]=D;
					}
				}
			}
			//搜索所有可以达到的状态,求最小值。 
			For(j,1<<N){
				if(~dp[M&1][j]){
					int tANS=dp[M&1][j];
					For(k,Wn) {
						if((j>>Want[k])&1) ;
						else tANS+=price[Want[k]];
					}
					if(tANS <ANS) ANS=tANS;
				}
			}
		}
		else{
			ANS=0;
			For(k,Wn) ANS+=price[Want[k]]; 
		}
		printf("%d\n",ANS);
	}
return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值