USACO 1.3

前言

这一章主要讲的是贪心和搜索


洛谷 1208 混合牛奶 Mixing Milk

题目

n n n个种类, a i a_i ai表示单价, b i b_i bi表示数量, 1 ≤ i ≤ n 1\leq i\leq n 1in,数量如果只选择部分,价格仍然不变,问买 m m m个最少需要的价钱


分析

选择单价更小的必然更优,所以说其实很容易想到按单价递增排序后的模拟过程


代码

/*
ID:lemond1
LANG:C++
TASK:milk
*/
#include <cstdio>
#include <algorithm>
#define rr register
using namespace std;
struct rec{
    int w,c;
    bool operator <(const rec &a)const{
        return w<a.w;
    }
}a[5001];
inline signed in(){
    rr int ans=0; rr char c=getchar();
    while (c<48||c>57) c=getchar();
    while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    return ans;
}
signed main(){
    freopen("milk.in","r",stdin);
    freopen("milk.out","w",stdout);
    rr int n,m,ans=0;
    m=in(); n=in();
    for (rr int i=1;i<=n;++i) a[i]=(rec){in(),in()};
    sort(a+1,a+1+n);
    for (rr int i=1;i<=n&&m;++i)
    if (a[i].c>=m) ans+=m*a[i].w,m=0;//如果直接可以满足供应完
    else ans+=a[i].c*a[i].w,m-=a[i].c;//只能买完还需要买
    printf("%d\n",ans);
    return 0;
}

洛谷 1209 修理牛棚 Barn Repair

题目

在一个数轴用最多 m m m条任意长度的胶带封住 n n n个缺口,问胶带总长度的最小值


分析

可以知道,缺口位置的差值越大,越应该分开,所以说贪心的思想就是一开始认为全部用一条封上,然后不断揭开


代码

/*
ID:lemond1
LANG:C++
TASK:barn1
*/
#include <cstdio>
#include <algorithm>
#define rr register
using namespace std;
int a[201],b[201];
inline signed in(){
    rr int ans=0; rr char c=getchar();
    while (c<48||c>57) c=getchar();
    while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    return ans;
}
signed main(){
    freopen("barn1.in","r",stdin);
    freopen("barn1.out","w",stdout);
    rr int lm=in();in();rr int n=in();
    for (rr int i=1;i<=n;++i) a[i]=in();
    sort(a+1,a+1+n);
    if (lm>=n) return !printf("%d\n",n);//特判
    for (rr int i=1;i<n;++i) b[i]=a[i+1]-a[i];//计算不封中间的差值
    sort(b+1,b+n); rr int ans=a[n]-a[1]+1;
    for (rr int i=n-1;i>n-lm;--i) ans-=b[i]-1;//要少减掉1
    return !printf("%d\n",ans);
}

洛谷 1211 牛式 Prime Cryptarithm

题目

in 洛谷


分析

暴力枚举,在此不多赘述


代码

/*
ID:lemond1
LANG:C++
TASK:crypt1
*/
#include <cstdio>
#define rr register
using namespace std;
int n,a[10],ans;
inline signed check(int x,int len){//计算是否只存在这几个数字且满足位数
    while (x){
        if (!a[x%10]) return 0; 
        x/=10; len--;
    }
    return !len;
}
signed main(){
    //freopen("crypt1.in","r",stdin);
    //freopen("crypt1.out","w",stdout);
    scanf("%d",&n);
    for (rr int i=1,x;i<=n;++i) scanf("%d",&x),a[x]=1;
    for (rr int i=1;i<10;++i) if (a[i])
    for (rr int j=1;j<10;++j) if (a[j])
    for (rr int k=1;k<10;++k) if (a[k])
    for (rr int p=1;p<10;++p) if (a[p]&&check((i*100+j*10+k)*p,3))
    for (rr int q=1;q<10;++q) if (a[q]&&check((i*100+j*10+k)*q,3))
    if (check((i*100+j*10+k)*(p*10+q),4)) ++ans;
    return !printf("%d\n",ans);
}

洛谷 2693 Combination Lock 号码锁

题目

in 洛谷


分析

so其实问题可以转换成250-重复的个数,那么重复的个数也就是可以通过乘法原理算出,就是两个号码的交集


代码

/*
ID:lemond1
LANG:C++
TASK:combo
*/
#include <cstdio>
#define min(a,b) ((a)<(b))?(a):(b)
#define rr register
using namespace std;
signed main(){
	freopen("combo.in","r",stdin);
	freopen("combo.out","w",stdout);
	rr int n,a,b,c,d,e,f;
	scanf("%d%d%d%d%d%d%d",&n,&a,&b,&c,&d,&e,&f);
	if (n<5) return !printf("%d\n",n*n*n);
	if (a>d) a^=d,d^=a,a^=d;
	if (b>e) b^=e,e^=b,b^=e;
	if (c>f) c^=f,f^=c,c^=f;
	rr int t1=min(d-a,a+n-d),t2=min(e-b,b+n-e),t3=min(f-c,c+n-f);
	printf("%d\n",250-(5-t1)*(t1<5)*(5-t2)*(t2<5)*(5-t3)*(t3<5));
}

洛谷 3650 滑雪课程设计 Ski Course Design

题目

n n n个数变成 x x x x + 17 x+17 x+17的范围,变成 n ± y , y ∈ N ∗ n\pm y,y\in N* n±y,yN,需要 y 2 y^2 y2的价钱,每个数只能变1次,问最少价钱是多少 x 不 定 x不定 x


分析

讲到这里,暴力枚举x,然后模拟就不多说了


代码

/*
ID:lemond1
LANG:C++
TASK:skidesign
*/
#include <cstdio>
#define rr register
using namespace std;
int n,a[1001];
inline signed in(){
	rr int ans=0; rr char c=getchar();
	while (c<48||c>57) c=getchar();
	while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
	return ans;
}
signed main(){
	freopen("skidesign.in","r",stdin);
	freopen("skidesign.out","w",stdout);
	n=in(); rr int ans=2147483647;
	for (rr int i=1;i<=n;++i) a[i]=in();
	for (rr int j=0;j<84;++j){
		rr int sum=0;
		for (rr int i=1;i<=n;++i)
		if (a[i]<j) sum+=(j-a[i])*(j-a[i]);
		else if (a[i]>j+17) sum+=(a[i]-j-17)*(a[i]-j-17);
		ans=(ans<sum)?ans:sum;
	}
	return !printf("%d\n",ans);
}

洛谷 1444 虫洞 wormhole

题目

问一个无向关系图中有多少个环


分析

由于关系是不定的,所以对于虫洞的配对用深搜解决后,再判断是否形成环


代码

/*
ID:lemond1
LANG:C++
TASK:wormhole
*/
#include <cstdio>
#include <algorithm>
#define rr register
using namespace std;
struct site{
    int x,y;
    bool operator<(const site &a)const{
	    return (y!=a.y)?y<a.y:x<a.x;
	}
}a[13];
int n,f[13],to[13],ans;
inline signed in(){
	rr int ans=0; rr char c=getchar();
	while (c<48||c>57) c=getchar();
	while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
	return ans;
}
inline signed rep(int x){
	rr int vis=0;
	while (to[x]){//判环
		if (vis&(1<<x-1)) return 1;
		vis|=(1<<x-1);
		x=f[to[x]];
	}
	return 0;
}
inline void dfs(int dep){
	if (dep>n){
		bool flag=0;
		for (rr int i=1;i<=n&&!flag;++i) flag=rep(i);
		ans+=flag;
		return;
	}
	if (f[dep]) dfs(dep+1);//如果已经找到虫洞了
	else for (rr int i=dep+1;i<=n;++i)
	if (!f[i]){
		f[i]=dep; f[dep]=i;
		dfs(dep+1);
		f[i]=f[dep]=0;
	}
}
signed main(){
	freopen("wormhole.in","r",stdin);
	freopen("wormhole.out","w",stdout);
	n=in();
	for (rr int i=1;i<=n;++i) a[i]=(site){in(),in()};
	sort(a+1,a+1+n);
	for (rr int i=1;i<n;++i) if (a[i].y==a[i+1].y) to[i]=i+1;
	dfs(1);
	return !printf("%d\n",ans);
}

后续

Fighting!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值