UVa:10306 e-Coins

来源:互联网 发布:音乐播放器排行榜知乎 编辑:程序博客网 时间:2024/05/24 01:29

灵感来自题下面那个图。

一开始想用dp[i][j]表示前i个coin得到j时的最少硬币数,但是后来想了想不满足无后效性。于是转化为dp[i][j][k]表示前i种硬币,分别得到x为j,y为k时的最少硬币数。这样答案就是dp[i][j][k],i==m,j*j+k*k==S*S的时候。这样对于每个coin,就那个图而言,枚举它每个终点,然后dp即可。一开始不知道哪写错了,还加了排序,一直没过样例,后来想了想发现数组的第一维没有必要写,排序也没必要写。然后就过了。。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define ll long long#define MAXN 305#define INF 2139062143using namespace std;int dp[MAXN][MAXN];int main(){    int T;    scanf("%d",&T);    while(T--)    {        int m,S;        scanf("%d%d",&m,&S);        int x[45],y[45];        memset(dp,0x7f,sizeof(dp));        for(int i=0; i<m; ++i)            scanf("%d%d",&x[i],&y[i]);        dp[0][0]=0;        for(int i=0; i<m; ++i)        {            for(int j=0; j<=S; ++j)                for(int k=0; k<=S; ++k)                    if(j>=x[i]&&k>=y[i])                        dp[j][k]=min(dp[j][k],dp[j-x[i]][k-y[i]]+1);        }        int ans=INF;        for(int i=0; i<=S; ++i)            for(int j=0; j<=S; ++j)                if(i*i+j*j==S*S&&dp[i][j])                    ans=min(ans,dp[i][j]);        if(ans!=INF)  printf("%d\n",ans);        else  puts("not possible");    }    return 0;}


 

0 0
原创粉丝点击