题目
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 2611 | Accepted: 1069 |
Description
Input
Output
Sample Input
3 6 10 1 1 100 5 120
Sample Output
111
Hint
想法
之前为了这道题看了好多的解题报告,然而大部分代码都是一样的,而且解题过程写的也不是特别容易理解= =... 作为初学者的我看了一天多都没明白。其实仔细想想也是很容易理解的。
首先,大于等于C的直接支付一天,无需考虑。
对于小于C的情况,先选择大的货币,但是不超出C,如果正好(left=0)那就直接计算最大支付天数(canpayday)然后按照比例减去货币。
如果没凑齐,(left>0)那么从面值小的向大的方向凑齐,这个过程中如果凑齐了那就计算canpayday,按比例减去.
如果还没凑齐,那基本上就是没有货币了。break掉。
大概思路就是这样,下面贴代码
View Source On GitHub
#include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #include <algorithm> using namespace std; struct cash { int value; int amount; }; bool cmp(const cash& a,const cash& b) { return a.value<b.value; } int need[64]; int makedayfrom(vector<cash>& vec,int C) { memset(need,0,sizeof(int)*64); int N=vec.size(); int left=C; for(int i=N-1;i>=0;i--) {// if(vec.at(i).amount>0&&left>0) { int x=left/vec.at(i).value; x=min(x,vec.at(i).amount); need[i]=x; left-=x*vec.at(i).value; } } if(left>0) { for(int i=0;i<N;i++) { if(vec.at(i).amount>need[i]&&left>0) { int x=left/vec.at(i).value; if(x==0) { /// try to make x = 1 need[i]++; left=0; break; } } } } if(left>0) { return -1; } int canpayday=2<<29; for(int i=0;i<64;i++) { if(need[i]>0) { canpayday=min(canpayday,vec.at(i).amount/need[i]); } } if(canpayday<=0) return -1; for(int i=0;i<N;i++) { if(need[i]>0) { vec.at(i).amount-=canpayday*need[i]; } } return canpayday; } int main() { int N,C; scanf("%d %d",&N,&C); vector<cash> vec; int ans=0; for(int i=0;i<N;i++) { cash s; scanf("%d %d",&s.value,&s.amount); vec.push_back(s); } sort(vec.begin(),vec.end(),cmp); for(int i=N-1;i>=0;i--) { if(vec.at(i).value>=C) { ans+=vec.at(i).amount; vec.pop_back(); } else break; } int tmp; while((tmp=makedayfrom(vec,C))>0) { ans+=tmp; } printf("%d\n",ans); return 0; }中间还参考了一些别的代码,直接上链接:
View Source On GitHub
View Source On GitHub
View Source On GitHub
我在GitHub上建立了一个仓库,用于存放已经AC的题目的源代码。如果各位有未收录的题目或者有更好的解法,欢迎fork仓库+PR~ 让我们共同创建一个AC代码集中仓库,造福ACM Beginner ~
仓库地址: OJ-Problems-Source On GitHub