1.硬币问题
a.题目:给定面值不同的m种硬币,求支付n元时的最少硬币数,各硬币可以重复使用
b.核心思路:关键在于使用T[i]j[j]表示用第i种硬币支付j元的情况,这表示是否使用第i种硬币
a.现有价值为Vi,重量为Wi的N个物品,容易为W的背包,请求出总价值尽可能高并且总重不超过W的总价值的最大值。
b.核心:C[N+1][W+1]是表示前i个物品装入容量为w的背包时总价值的最大值
c.代码:
a.题目:求由H*W个小方格组成的一组方格内,除去污点之外的干净瓷砖的最大正方形面积
b.核心:dp[i][j]中存储着当前坐标(i,j)向左上方扩展可形成的最大正方形的边长,然后用动态规划法依次计算dp[i][j]即可
a.题目:给定面值不同的m种硬币,求支付n元时的最少硬币数,各硬币可以重复使用
b.核心思路:关键在于使用T[i]j[j]表示用第i种硬币支付j元的情况,这表示是否使用第i种硬币
c.代码:
//
// Created by 叶子 on 2018/2/8.
// 硬币问题
//
#include "iostream"
using namespace std;
static const int NMAX = 50000;
static const int INFTY = ( 1 << 30);
int main(){
int n,m;
int C[21];
int T[NMAX + 1];
cin >> n >> m;
for ( int i = 1; i <= m ; i ++){
cin >> C[i];
}
for ( int i = 0 ; i <=NMAX ; i ++) T[i] = INFTY;
T[0] = 0;
for ( int i = 1 ; i <= m ; i ++){
for ( int j = 0 ; j + C[i] <=n ; j ++){
T[j + C[i]] = min(T[j+C[i]],T[j] + 1);
}
}
cout << T[n] << endl;
return 0;
}
2.背包问题:
a.现有价值为Vi,重量为Wi的N个物品,容易为W的背包,请求出总价值尽可能高并且总重不超过W的总价值的最大值。
b.核心:C[N+1][W+1]是表示前i个物品装入容量为w的背包时总价值的最大值
c.代码:
//
// Created by 叶子 on 2018/2/9.
// 背包问题
//
#include "iostream"
#include "vector"
#include "algorithm"
static const int NMAX = 105;
static const int WMAX = 10005;
static const int DIAGONAL = 1;
static const int TOP = 0 ;
using namespace std;
struct Item {
int value,weight;
};
int N,W;
Item items[NMAX+1];
int C[NMAX + 1][NMAX + 1],G[NMAX+1][WMAX+1];
void compute(int &maxValue,vector<int> &selection){
for ( int w = 0 ; w <= W ; w ++){
C[0][w] = 0;
G[0][w] = DIAGONAL;
}
for ( int i = 1 ; i <= N ; i ++) C[i][0] = 0;
for ( int i = 1 ; i <= N ; i ++){
for ( int w = 1 ; w <=W ; w++){
C[i][w] = C[i-1][w];
G[i][w] = TOP;
if ( items[i].weight > w ) continue;
if ( items[i].value + C[i-1][w-items[i].weight] > C[i-1][w] ) {
C[i][w] = items[i].value + C[i-1][w-items[i].weight];
G[i][w] = DIAGONAL;
}
}
}
maxValue = C[N][W];
selection.clear();
for ( int i = N,w=W;i>=1;i--){
if (G[i][w] == DIAGONAL){
selection.push_back(i);
w -= items[i].weight;
}
}
reverse(selection.begin(),selection.end());
}
void input(){
cin >> N >> W;
for ( int i = 1 ; i <=N ; i ++){
cin >> items[i].value >> items[i].weight;
}
}
int main(){
int maxValue;
vector<int> selection;
input();
compute(maxValue,selection);
cout << maxValue << endl;
return 0;
}
3.最大正方形:
a.题目:求由H*W个小方格组成的一组方格内,除去污点之外的干净瓷砖的最大正方形面积
b.核心:dp[i][j]中存储着当前坐标(i,j)向左上方扩展可形成的最大正方形的边长,然后用动态规划法依次计算dp[i][j]即可
c.代码:
//
// Created by 叶子 on 2018/2/9.
// 正方形问题
//
#include "cstdio"
#include "algorithm"
using namespace std;
static const int MAX = 2400;
int dp[MAX][MAX],G[MAX][MAX];
int getLargestSquare(int H,int W){
int maxWidth = 0;
for ( int i = 0 ; i < H ; i ++){
for ( int j = 0 ; j < W ; j ++){
dp[i][j] = ( G[i][j] + 1 ) % 2;
maxWidth |= dp[i][j];
}
}
for ( int i = 1 ; i < H ; i ++){
for ( int j = 1 ; j < W ; j ++){
if ( G[i][j]) {
dp[i][j] = 0 ;
}else{
dp[i][j] = min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1])) + 1;
maxWidth = max(maxWidth,dp[i][j]);
}
}
}
return maxWidth * maxWidth;
}
int main(void){
int H,W;
scanf("%d %d",&H,&W);
for ( int i = 0 ; i <H ; i ++){
for ( int j = 0 ; j < W; j ++) scanf("%d",&G[i][j]);
}
printf("%d\n",getLargestSquare(H,W));
return 0;
}