USACO4.1.1--Beef McNuggets

chunlvxiong的博客


题目描述:

  有N种包装盒(1≤N≤10),每种包装盒可以包装牛块i块(1≤i≤256),每种包装盒可以使用任意次。求无法包装的最大的牛块数,若所有数目的牛块都能被包装,或者无法包装的最大牛快数为oo,那么输出0。

思考&分析:

  其实这是个数论问题--给定N个数,求不能由这些数通过加减得到的最大数。

  如果只有两个数,那么这个问题比较经典,也存在如下结论:若gcd(p,q)==1 ,则px+qy不能表示的最大数为pq-p-q

  如果N个数中没有任何两个数的GCD==1的话,那么最大的不能得到的数一定是oo,因为这N个数必然存在一个非1公因子X,从而使组成的数均为X的倍数,%X!=0的数将无法组成。

  除去这种情况,答案最大只有256^2,那么使用DP解决即可:用dp[i][j]表示前i个数能否表示j,方程如下:

  dp[i][j]=dp[i][j] or dp[i-1][j-k*num[i]](k>=0 && j>=k*num[i])

  这里利用完全背包的思想进行优化,可以把方程改为:

  dp[j]=dp[j] or dp[j-num[i]](j>=num[i],同时继承时从小到大继承)

  这样时间复杂度O(N*256^2),空间复杂度O(256^2)-->可以顺利AC此题。

  其实我更想谈的是另一种想法:

  设这N个数的最小值为T,则如果X能被组成的话,X+KT也能被组成(K>=0),所以你可以认为要求%T=X的最小的数。

  这是一个最短路问题:把%T==0/1/2……T-1看成T个点,每个点都会连出N条边(X-->(X+A[i])%T,权值为A[i]),共N*T条边,并不多,可以跑SPFA解决。

  接下来对于结果(dis数组)有以下几种情况:

    dis[i]==i表示%T==i的所有数都能被组成-->如果所有的dis[i]==i表示所有数都能被组成,输出0。

    dis[i]==oo表示%T==i的所有数都不能被组成-->表示最大不能被组成的数是oo,输出0。

    dis[i]=X表示%T==i的最小能被组成的数是X-->%T==i的最大不能被组成的数是X-T,取MAX即可。

  这样就可以得到结果了,如果用SPFA写时间复杂度O(T*N*T)(远不会到这个上限),用dijkstra写时间复杂度O(T*T),加堆优化可以达到O((T+N*T)log(N*T)),可以解决规模更大的问题。

贴代码:

数论+DP:

#include<bits/stdc++.h>
using namespace std;
const int Max=256*256;
int n,a[15],dp[Max+5];
int gcd(int a,int b){
    if (!b) return a; else return gcd(b,a%b);
}
bool check(){
    for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
    if (gcd(a[i],a[j])==1)
        return 0;
    return 1;
}
int main(){
    freopen("nuggets.in","r",stdin);
    freopen("nuggets.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    if (check()){
        puts("0");
        return 0;
    }
    memset(dp,0,sizeof(dp));
    dp[0]=1;
    for (int i=1;i<=n;i++)
    for (int j=a[i];j<=Max;j++)
        dp[j]|=dp[j-a[i]];
    int ans=0;
    for (int i=Max;i>=1;i--)
    if (!dp[i]){
        ans=i;
        break;
    }
    printf("%d\n",ans);
    return 0;
}

最短路:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll oo=1e13;
const int maxn=305;
const int maxm=3005;
int head[maxn],Q[maxn],tot;
ll dis[maxn];
int T,n,a[15],front,rear;
bool vis[maxn];
struct E{
    int to,len,next;
}edge[maxm];
void init(){
    memset(head,0,sizeof(head)),tot=0;
}
void makedge(int u,int v,int t){
    edge[++tot].to=v;
    edge[tot].len=t;
    edge[tot].next=head[u];
    head[u]=tot;
}
void push(int x){
    vis[x]=1;
    Q[rear]=x;
    rear=(rear+1)%maxn;
}
void spfa(){
    int u,v;
    memset(dis,1,sizeof(dis));
    memset(vis,0,sizeof(vis));
    front=rear=dis[0]=0,push(0);
    while (front!=rear){
        u=Q[front];
        for (int i=head[u];i;i=edge[i].next){
            v=edge[i].to;
            if (dis[u]+edge[i].len<dis[v]){
                dis[v]=dis[u]+edge[i].len;
                if (!vis[v]) push(v);
            }
        }
        front=(front+1)%maxn;
    }
}
int main(){
    freopen("nuggets.in","r",stdin);
    freopen("nuggets.out","w",stdout);
    scanf("%d",&n);
    T=1<<30;
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i]),T=min(T,a[i]);
    for (int i=1;i<=n;i++)
    for (int j=0;j<T;j++)
        makedge(j,(j+a[i])%T,a[i]);
    spfa();
    ll ans=0;
    for (int i=0;i<T;i++)
    if (dis[i]>i)
        ans=max(ans,dis[i]-T);
    if (ans<oo) printf("%lld\n",ans); else puts("0");
    return 0;
}
时间: 2024-08-08 01:26:13

USACO4.1.1--Beef McNuggets的相关文章

USACO 4.1 Beef McNuggets

Beef McNuggetsHubert Chen Farmer Brown's cows are up in arms, having heard that McDonalds is considering the introduction of a new product: Beef McNuggets. The cows are trying to find any possible way to put such a product in a negative light. One st

P2737 [USACO4.1]麦香牛块Beef McNuggets(完全背包+数论确定上界)

题目链接:https://www.luogu.org/problem/show?pid=2737 题目大意:农夫布朗的奶牛们正在进行斗争,因为它们听说麦当劳正在考虑引进一种新产品:麦香牛块.奶牛们正在想尽一切办法让这种可怕的设想泡汤.奶牛们进行斗争的策略之一是“劣质的包装”.“看,”奶牛们说,“如果你只用一次能装3块.6块或者10块的三种包装盒包装麦香牛块,你就不可能满足一次只想买1.2.4.5.7.8.11.14或者17块麦香牛块的顾客了.劣质的包装意味着劣质的产品.” 你的任务是帮助这些奶牛

洛谷——P2737 [USACO4.1]麦香牛块Beef McNuggets

https://www.luogu.org/problemnew/show/P2737 题目描述 农夫布朗的奶牛们正在进行斗争,因为它们听说麦当劳正在考虑引进一种新产品:麦香牛块.奶牛们正在想尽一切办法让这种可怕的设想泡汤.奶牛们进行斗争的策略之一是“劣质的包装”.“看,”奶牛们说,“如果你只用一次能装3块.6块或者10块的三种包装盒包装麦香牛块,你就不可能满足一次只想买1.2.4.5.7.8.11.14或者17块麦香牛块的顾客了.劣质的包装意味着劣质的产品.” 你的任务是帮助这些奶牛.给出包装

[Luogu2737] [USACO4.1]麦香牛块Beef McNuggets

题目描述 农夫布朗的奶牛们正在进行斗争,因为它们听说麦当劳正在考虑引进一种新产品:麦香牛块.奶牛们正在想尽一切办法让这种可怕的设想泡汤.奶牛们进行斗争的策略之一是“劣质的包装”.“看,”奶牛们说,“如果你只用一次能装3块.6块或者10块的三种包装盒包装麦香牛块,你就不可能满足一次只想买1.2.4.5.7.8.11.14或者17块麦香牛块的顾客了.劣质的包装意味着劣质的产品.” 你的任务是帮助这些奶牛.给出包装盒的种类数N(1<=N<=10)和N个代表不同种类包装盒容纳麦香牛块个数的正整数(1&

P2737 [USACO4.1]麦香牛块Beef McNuggets

题目描述 农夫布朗的奶牛们正在进行斗争,因为它们听说麦当劳正在考虑引进一种新产品:麦香牛块.奶牛们正在想尽一切办法让这种可怕的设想泡汤.奶牛们进行斗争的策略之一是“劣质的包装”.“看,”奶牛们说,“如果你只用一次能装3块.6块或者10块的三种包装盒包装麦香牛块,你就不可能满足一次只想买1.2.4.5.7.8.11.14或者17块麦香牛块的顾客了.劣质的包装意味着劣质的产品.” 你的任务是帮助这些奶牛.给出包装盒的种类数N(1<=N<=10)和N个代表不同种类包装盒容纳麦香牛块个数的正整数(1&

【洛谷P2737】Beef McNuggets

首先有这样一个结论:若p,q为自然数,且gcd(p,q)=1,那么px+qy不能表示的最大数为pq-p-q 那么本题中p,q均取决于最大的两个数,不妨取256,那么上界为256^2-256*2 之后就是简单的完全背包 如果数据中有1,或者最大不能取到的数大于上界,就是0 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=256

杭电ACM分类

杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDIATE DECODABILITY

【转】对于杭电OJ题目的分类

[好像博客园不能直接转载,所以我复制过来了..] 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDI

转载:hdu 题目分类 (侵删)

转载:from http://blog.csdn.net/qq_28236309/article/details/47818349 基础题:1000.1001.1004.1005.1008.1012.1013.1014.1017.1019.1021.1028.1029. 1032.1037.1040.1048.1056.1058.1061.1070.1076.1089.1090.1091.1092.1093. 1094.1095.1096.1097.1098.1106.1108.1157.116