uva 10306 - e-Coins

题目链接

题意:100组数据,给出m~40和s~300, 再给出m种电子硬币,每种硬币有两种金额xi,yi。现在要在m种硬币种选若干个硬币,可以重复选同一种硬币, 使得(x1 + x2 + .... + xn) ^ 2 + (y1 + y2 + ... + yn) ^ 2 == s * s, 要求n尽量小,(n为选取硬币的个数), 如果不能选出满足条件的硬币,输出-1。

题解:很简单,就是dp【i】【j】就好,每次都有可能达到s*s,都要更新下ans

重点:二维完全背包

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)

typedef long long ll;

using namespace std;

const int maxn = 300 + 10;
const int INF = INT_MAX/2 - 1;
int dp[maxn][maxn], s, n;
int ans;

struct info
{
    int x, y;
};
info ren[maxn];

void getDp()
{
    ans = INF;
    memset(dp, -1, sizeof(dp));//不能达到
    dp[0][0] = 0;//初始化
    for(int i = 1;i <= n;i++)
    {
        for(int a = ren[i].x;a <= s;a++)//二维背包从小到大
        {
            for(int b = ren[i].y;b <= s;b++)//也是从小到大
            {
                if(dp[a-ren[i].x][b-ren[i].y]!=-1&&( dp[a][b]==-1|| (dp[a-ren[i].x][b-ren[i].y]+1<dp[a][b]) ) )//可以更新dp【a】【b】
                {
                    dp[a][b] = dp[a-ren[i].x][b-ren[i].y]+1;
                    if(a*a + b*b == s*s)//直接统计就好
                    {
                        ans = min(ans, dp[a][b]);
                    }
                }
            }
        }
    }
}
void solve()
{
    getDp();
    if(ans != INF)
        printf("%d", ans);
    else
    {
        printf("not possible");
    }
    printf("\n");
}

int main()
{
  //  freopen("3Cin.txt", "r", stdin);
    //freopen("3Cout.txt", "w", stdout);
    int ncase;
    scanf("%d", &ncase);
    while(ncase--)
    {
        scanf("%d%d", &n, &s);
        REP_D(i, 1, n)
        {
            scanf("%d%d", &ren[i].x, &ren[i].y);
        }
        solve();
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值