# [USACO13NOV]没有找零No Change 题解

### 输入输出格式

#### 输入格式：

• Line 1: Two integers, K and N.

• Lines 2..1+K: Each line contains the amount of money of one of FJ's coins.

• Lines 2+K..1+N+K: These N lines contain the costs of FJ's intended purchases.

#### 输出格式：

• Line 1: The maximum amount of money FJ can end up with, or -1 if FJ cannot complete all of his purchases.

3 6
12
15
10
6
3
3
2
3
7

12

### 说明

FJ has 3 coins of values 12, 15, and 10. He must make purchases in sequence of value 6, 3, 3, 2, 3, and 7.

FJ spends his 10-unit coin on the first two purchases, then the 15-unit coin on the remaining purchases. This leaves him with the 12-unit coin.

$$dp_{sta}$$表示状态为$$sta$$时（二进制，表示哪些硬币使用了，哪些没使用），从一号物品开始能购买的物品数量

$$dp[new\_sta]=max(dp[new\_sta],k)$$

$$sum_k$$表示前$$i$$个物品的总售价

#include<bits/stdc++.h>
#define ll long long
#define INF 2147483647
#define mem(i,j) memset(i,j,sizeof(i))
#define F(i,j,n) for(register int i=j;i<=n;i++)
#define lowbit(i) i&(-i)
using namespace std;
int k,n,c[20],p[100010],dp[1100000],sum[100010];
int datta=0;char chchc=getchar();bool okoko=0;
while(chchc<'0'||chchc>'9'){if(chchc=='-')okoko=1;chchc=getchar();}
while(chchc>='0'&&chchc<='9'){datta=datta*10+chchc-'0';chchc=getchar();}
return okoko?-datta:datta;
}
int main(){
F(i,1,k)
F(i,1,n)
mem(dp,-1);
dp[0]=0;
int ans=2147483647;
F(sta,0,(1<<k)-1){
if(dp[sta]==-1)
continue;
if(dp[sta]==n){
int _ans=0;
F(i,1,k)
if(sta&(1<<(i-1)))
_ans+=c[i];
ans=min(ans,_ans);
continue;
}
F(i,1,k){
if(sta&(1<<(i-1)))
continue;
int l=dp[sta]+1,r=n,mid,_ans=-1;
while(l<=r){
mid=(l+r)>>1;
if(sum[mid]<=sum[dp[sta]]+c[i])
l=mid+1,_ans=mid;
else
r=mid-1;
}
if(_ans==-1)
continue;
dp[sta|(1<<(i-1))]=max(dp[sta|(1<<(i-1))],_ans);
}
}
printf("%d\n",ans==2147483647?-1:c[0]-ans);
return 0;
}

posted @ 2019-02-17 23:54  hzf29721  阅读(224)  评论(0编辑  收藏  举报