AtCoder Beginner Contest 286——D - Money in Hand

AtCoder Beginner Contest 286 题目讲解

A题 B题 C题 D题 E题


蒟蒻来讲题,还望大家喜。若哪有问题,大家尽可提!

Hello, 大家好哇!本初中生蒟蒻今天以AtCoder Beginner Contest 286的D题——Money in Hand为例,给大家讲解一下判断图中存在闭环的常用方法!

===========================================================================================

原题

Problem Statement

Takahashi has N N N kinds of coins; specifically, for 1 ≤ i ≤ N 1\leq i\leq N 1iN, he has B i B_{i} Bi​ coins worth A i A_{i} Ai​ yen (the currency in Japan) each.

Determine if Takahashi can pay exactly X X X yen (without change) with the coins he currently has.

Constraints

  • 1 ≤ N ≤ ≤ 50 1\leq N≤\leq 50 1N≤≤50
  • 1 ≤ X ≤ 1 0 4 1\leq X\leq 10^4 1X104
  • 1 ≤ A i ​ ≤ 100 1\leq A_{i}​\leq 100 1Ai100
  • 1 ≤ B i ≤ 50 1\leq B_{i}\leq 50 1Bi50
  • A i A_{i} Ai​ are pairwise distinct.
  • All values in the input are integers.

Input

The input is given from Standard Input in the following format:

N  X
A1​  B1​
A2​  B2​
⋮
AN​  BN​

Output

Print Yes if Takahashi can pay exactly X X X yen with the coins he currently has; print No otherwise.

Sample Input 1

2 19
2 3
5 6

Sample Output 1

Yes

Takahashi has three 2 2 2-yen coins and six 5 5 5-yen coins. He can use two 2 2 2-yen coins and three 5 5 5-yen coins to pay exactly 2 × 2 + 5 × 3 = 19 2×2+5×3=19 2×2+5×3=19 yen. Thus, Y e s Yes Yes should be printed.

Sample Input 2

2 18
2 3
5 6

Sample Output 2

No

There is no combination of the coins that he can use to pay exactly 18 18 18 yen. Thus, N o No No should be printed.

Sample Input 3

3 1001
1 1
2 1
100 10

Sample Output 3

Yes

He need not use all kinds of coins.


思路

这道题真的挺简单,就是一个裸的恰好装满的多重背包问题,所以直接套模板即可。我们知道多重背包有三种解决方式,由于这道题数据比较少,三种都能用!(因为大家应该都会了,所以在此不一一讲解,若有不会的,私聊我,我一定竭尽所力的讲解)

三种代码

N为物品数量,V为物品最多的重量,S为物品的个数

第一种(时间复杂度: O ( N × V × S ) O(N\times V\times S) O(N×V×S)

#include 

using namespace std;

const int M = 1e4 + 10;

int n, x;
int w[M], s[M];
bool dp[M];

int main()
{
	cin.tie(0);
	ios :: sync_with_stdio(0);
	
	cin >> n >> x;
	
	for (int i = 1; i <= n; i ++)
		cin >> w[i] >> s[i];
	
	dp[0] = 1;
	for (int i = 1; i <= n; i ++)
		for (int j = x; j >= 0; j --)
			for (int k = 1; k <= s[i] && k * w[i] <= j; k ++)
				dp[j] |= dp[j - w[i] * k];
				
	if (dp[x]) cout << "Yes" << endl;
	else cout << "No" << endl;
	
	return 0;
}

第二种二进制优化(时间复杂度: O ( N × V × l o g ( S ) ) O(N\times V\times log(S)) O(N×V×log(S))

#include 
#include 
#include 

using namespace std;

const int N = 2e4 + 10;

int n, w;
int wt[N], vl[N], sz[N];
int f[N];

int main()
{
    cin >> n >> w;
    
    int ww, vv, ss;
    int cnt = 0;
    for (int i = 1; i <= n; i ++)
    {
        cin >> ww >> ss;
        
        int k = 1;
        while (k <= ss)
        {
            wt[++ cnt] = ww * k;
            ss -= k;
            k *= 2;
        }
        if (ss)
        {
            wt[++ cnt] = ww * ss;
        }
    }
    
    f[0] = 1;
    for (int i = 1; i <= cnt; i ++)
        for (int j = w; j >= wt[i]; j --)
            f[j] |= f[j - wt[i]];
            
    cout << ((f[w]) ? "Yes" : "No") << endl;
}

第三种单调队列优化(时间复杂度: O ( N × V ) O(N\times V) O(N×V)

#include 
#include 
#include 

using namespace std;

const int N = 2e4 + 10;

int n, W;
int q[N], g[N], f[N];

int main()
{
    cin >> n >> W;
    
    f[0] = 1;
    for (int i = 0; i < n; i ++ )
    {
        int w, v, s;
        cin >> w >> s;
        
        memcpy(g, f, sizeof f);
        for (int j = 0; j < w; j ++)
        {
            int h = 0, t = -1;
            for (int k = j; k <= W; k += w)
            {
                if (h <= t && k - s * w > q[h]) h ++;
                
                while (h <= t && g[q[t]] <= g[k]) t --;
                
                if (h <= t) f[k] |= g[q[h]];
                q[++ t] = k;
            }
        }
    }
    
    (f[W]) ? puts("Yes") : puts("No");
}

今天就到这里了!

大家有什么问题尽管提,我都会尽力回答的!最后,除夕夜祝大家新年快乐!
在这里插入图片描述

吾欲您伸手,点的小赞赞。吾欲您喜欢,点得小关注!

你可能感兴趣的:(算法-DP,算法,动态规划,图论)