# 完全背包练习总结

01背包是这个套路

#include<iostream>
#include<cstring>
using namespace std;
int length;
int shuzu[10005];
int w[501], v[501];

int main(){
int jishu;
cin >> jishu;
while(jishu -- ){
memset(shuzu, 0x3f, sizeof(shuzu));
shuzu[0] = 0;
int a , b;
cin >> a >> b;
length = b - a + 1;
int num ;
cin >> num;
for(int i = 0; i < num; i++) cin >> v[i] >> w[i];

for(int i = 0; i < num; i++){
for(int j = 0; j+w[i] < length; j++){
if(j%w[i]!=0 && shuzu[j]==0x3f3f3f3f) continue;
if(shuzu[j+w[i]] > shuzu[j]+v[i])
shuzu[j+w[i]] = shuzu[j] + v[i];
}
}

if(shuzu[length-1] == 0x3f3f3f3f)
cout << "This is impossible." << endl;
else
cout << "The minimum amount of money in the
piggy-bank is "<<shuzu[length-1]<<"." << endl;
}
return 0;
}

# 多重背包

1块钱：25张 ， 5块钱：12张 ， 10块钱：0张 ， 25块钱：1张

1块钱： 凑不够
5块钱： 可以！！ 12张5块刚刚60三 （5角钱~~~）
10块钱：得都莫得说啥子喃说
25块钱：可以一张25块钱+25张1块钱，这儿就有26张了，所以不能一发现凑够就结束

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef struct Node{
int data;
int arr[4];
Node(){
data = 0;
arr[0] = arr[1] = arr[2] = arr[3] = 0;
}
}Node;
int length;
int coin[4];
Node shuzu[10010];
int value[4] = {1, 5, 10, 25};

void tovalue(Node &n1, Node &n2){
n1.data = n2.data;
for(int i = 0; i < 4; i++)
n1.arr[i] = n2.arr[i];
}

void print(){
for(int i = 0; i <= length; i++){
cout << " (";
for(int j = 0; j < 4; j++){
cout << shuzu[i].arr[j] << " ";
//              cout << shuzu[i].data << " ";
}
cout << shuzu[i].data << " ";
cout <<"\b)" ;
}
cout << endl;
}

int main(){
while(cin >> length >> coin[0] >> coin[1] >> coin[2] >> coin[3]){
if(!length && !coin[0] && !coin[1]
&& !coin[2] && !coin[3]) break;
memset(shuzu, 0, sizeof(shuzu));
for(int i = 0; i < 4; i++){
for(int j = 1; j <= length; j++){
if(shuzu[j].data == 0){
if(j%value[i]==0 && j/value[i]<=coin[i]){
shuzu[j].data = j/value[i];
shuzu[j].arr[i] = j/value[i];
}
}else{
if(shuzu[j+value[i]].data >= shuzu[j].data+1
|| shuzu[j].arr[i]>=coin[i]
|| j+value[i]>length) continue;
tovalue(shuzu[j+value[i]], shuzu[j]);
shuzu[j+value[i]].data ++;
shuzu[j+value[i]].arr[i] ++;
}
}
//          print();
}

if(shuzu[length].data!=0)
printf("Throw in %d cents
, %d nickels, %d dimes, and %d quarters."
,shuzu[length].arr[0],shuzu[length].arr[1]
,shuzu[length].arr[2],shuzu[length].arr[3]);
else
cout << "Charlie cannot buy coffee.";
cout << endl;
}
return 0;
}

31(B) , 33(A) , 41(B) , 43 (A) , 51(B) , 53(A)

#include<iostream>
#include<list>
using namespace std;
typedef struct Node{
int which;
int data;
Node(int w, int d){
which = w; data = d;
}
}Node;
int length;
int value[100] = {0};

bool cmp(Node a, Node b){
return a.data < b.data;
}

for(; start != end; start ++)
cout << "(" <<  (*start).data << ","
<< (*start).which<< ")  "<< " " ; cout << endl;
}

int main(){
for(int i = 2; i < 10; i++) value[i+'0'] = i * 10;
value['T'] = 100; value['J'] = 110; value['Q'] = 120;
value['K'] = 130;value['H'] = 4;   value['C'] = 1;
value['D'] = 2;   value['S'] = 3;
value['A'] = 200;
int jishu;
cin >> jishu;
while(jishu --){
cin >> length;
char a, b;
for(int i = 0; i < 2; i++){
for(int j = 0; j < length; j++){
cin >> a >> b;
}
}

list<Node>::iterator start = link.begin(), qian = start;
while(start != end){
while((*start).which!=1 && start!=end) start++;
if(start == end) break;
qian = start;
while(((*qian).which!=2 || (*qian).data==(*start).data)
&& qian!=end) qian ++;
if(qian == end) break;
}

}
return 0;
}

/*
1
6
JD 5D TC 2H 3H 4H
JH 4C 5H 2D 3D 4D
*/

5 = 1 + 1 + 1 + 1 + 1
5 = 2 + 1 + 1 + 1
5 = 2 + 2 + 1
5 = 3 + 1 + 1
5 = 3 + 2

dp就是先只有1的时候，更新数组，只有2的时候，跟新数组。。。。
1： 1 , 1 , 1 , 1 , 1
2： 1 , 2 , 2，3，3
3： 1，2，3，4，5
4： 1，2，3，4，6
dp[i][j] 就代表j这个数，在分解元素的时候，取i为最大元素时，有多少种情况

poj3181需要处理一哈数据，因为太大了long long装不下，double又不精准。。。

#include<iostream>    // 17
#include<ctime>
using namespace std;
#define N 100000000000000000
typedef struct Node{
long long rear,front;
Node(){rear = front = 0;}
}Node;
int length,row;
Node shuzu[105][1005];

int main(){
cin >> length >> row;
int clock1 = clock();
for(int i = 1; i <= length; i++) {
shuzu[1][i].rear = 1;
shuzu[1][i].front = 0;
}
for(int i = 2; i <= row; i++){
for(int j = 1; j < i; j++){
shuzu[i][j].rear = shuzu[i-1][j].rear;
shuzu[i][j].front = shuzu[i-1][j].front;
}
shuzu[i][i].front = shuzu[i-1][i].front
+ (shuzu[i-1][i].rear+1)/N;
shuzu[i][i].rear = (shuzu[i-1][i].rear + 1) % N;
for(int j = i+1; j <= length; j++){
shuzu[i][j].front = shuzu[i][j-i].front
+ shuzu[i-1][j].front
+ (shuzu[i][j-i].rear
+shuzu[i-1][j].rear)/N;
shuzu[i][j].rear =
(shuzu[i][j-i].rear + shuzu[i-1][j].rear) % N;
}
}

if(shuzu[row][length].front != 0)
cout << shuzu[row][length].front;
cout << shuzu[row][length].rear << endl;
//  cout << clock() - clock1 << endl;
//6604049133121382808    156581811045807 71094597751280645
return 0;
}

poj1742 是代表，经典的多重背包

#include<iostream>
#include<cstring>
using namespace std;
int row, length;
int v[105], count[105];
int shuzu[100005];

int main(){
while(cin >> row >> length && row && length){
for(int i = 0; i < row; i++) cin >> v[i];
for(int i = 0; i < row; i++) cin >> count[i];
memset(shuzu, -1, sizeof(shuzu));
shuzu[0] = 0;
for(int i = 0; i < row; i++){
for(int j = 0; j <= length; j++){
if(shuzu[j] >= 0){
shuzu[j] = count[i];
}else if(j-v[i]<0 || shuzu[j-v[i]]<=0){
shuzu[j] = -1;
}else{
shuzu[j] = shuzu[j-v[i]] - 1;
}
}
}

}