硬币组合 打怪兽
#include <iostream> #include <algorithm> using namespace std; int main(){
/*现有n种不同的硬币,要组合出1-X的任意面值,问至少需要多少个硬币
* 20 4
* 1 2 5 10
* 输出5
* 贪心求解
* 每次都拿当前可拿的最大的硬币
* */
int X,n; int coin[1005]; cin>>X>>n; for(int i=0;i<n;i++){ cin>>coin[i]; } sort(coin,coin+n);//将硬币有序排列,从小到大 int coinNumber = 0; int currentMoney = 0; while(true){ if(currentMoney >= X){ break; } else{ for(int i=n-1;i>=0;i--){ if(coin[i] <= currentMoney+1){
/*
* 当前已经能组成的钱是1到currentMoney,下一个要组成的钱数是currentMoney+1。从不超过currentMoney+1的硬币中取一个值最大的硬币p。
* 这样就能组成范围为1~current+p的钱数了。
* 最开始的时候currentMoney=0,要组成1。选取硬币1,可以组成1~1
* currentMoney=1,要组成2,选取硬币2,可以组成1~1+2
* currentMoney=3,要组成4,选取硬币2,可以组成1~3+2
* currentMoney=5,要组成6,选取硬币5,可以组成1~5+5
*
* */
coinNumber++; currentMoney += coin[i]; break; } } } } cout<<coinNumber<<endl; return 0; }
#include <iostream> using namespace std; int main(){
/* 打怪兽,每到一个怪兽,可以贿赂或者不贿赂,贿赂之后就可以带上这个怪兽,到下一个怪兽时如果当前武力值大于怪兽武力值,则不会被攻击。至少需要多少硬币。
* 武力值:8,5,10
* 金币:1,1,2
* 输出:2
* 需要注意的是可带不止一个怪兽
*
* 解法:背包
* dp[i][j] = max(dp[i-1][j],dp[i-1][j-cion[i]]+force[i]);
* 其中dp[i][j]表示包含第i个怪兽的情况下,用j个金币所能获得的最大武力值
* 只不过需要注意两个问题:
* 1、只有满足不贿赂怪兽i时的最大武力值 > 怪兽i的武力值时,才可以不贿赂怪兽i,即dp[i-1][j]
* 2、只有当前金币j大于贿赂怪兽i所需金币coin[i],并且剩余的金币j-coin[i]可以保证足够贿赂i之前的怪兽时才可以贿赂怪兽i,即dp[i-1][j-coin[i]];
*
* 初始条件:
* dp[0][j]=0;//0个怪兽始终获得武力0
* dp[i][0]=-1;//用0个金币贿赂怪兽不可行
* dp[i][j]=-1;//表示用j个硬币贿赂前i个怪兽不可行。如上面的例子:dp[1][1]=8。dp[3][1]=-1,用1个金币贿赂3个怪兽显然不可行。
*
* 最后一个怪兽n贿赂的情况在dp[n][j];j从小到达增长,如果用j个硬币贿赂n不可行,dp[n][j]=-1,找到第一个不为-1的dp[n][j],这个j即为所求。
*
* */
int n; cin>>n; int force[100]; int coin[100]; int dp[101][101]; for (int i = 1; i <= n; ++i) { cin>>force[i]; } for (int i = 1; i <=n ; ++i) { cin>>coin[i]; } for (int j = 0; j <=100 ; ++j) { dp[0][j]=0; } for (int i = 1; i <=n ; ++i) { for (int j = 0; j <=100 ; ++j) { dp[i][j]=-1; } } for (int i = 1; i <=n ; ++i) {//1-n个怪兽 for (int j = 1; j <=100 ; ++j) {//1-100个金币 if (dp[i-1][j] >= force[i]){ dp[i][j]=max(dp[i][j],dp[i-1][j]); } if(j>=coin[i] && dp[i-1][j-coin[i]]!=-1){ dp[i][j]=max(dp[i][j],dp[i-1][j-coin[i]]+force[i]); } //其实就是dp[i][j]=max(dp[i-1][j],dp[i-1][j-coin[i]]+force[i]);只不过加上了限制条件 } } int res=0; for (int j = 1; j <=100 ; ++j) { if(dp[n][j]!=-1){ res=j; break; } } cout<<res<<endl; return 0; }