本文主要是介绍10.12 新一波高能胡策题 贪心+状压DP+分块+魔性DP,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
- 出题人
- Problem 1 零花钱
- 题目来源
- 题目描述
- 题解
- 代码
- Problem 2 Oh My King
- 题目来源
- 题目描述
- 题解
- 代码
- Problem 3 函数求和
- 题目来源
- 题目描述
- Problem 4 防 AK 好题
- 题目来源
- 题目描述
出题人
(排名为字典序)
Chairman http://blog.csdn.net/qq_36693514
LXT http://blog.csdn.net/loi_lxtt
qrc 不用csdn的大佬
wyh 不用csdn的大佬
Problem 1 零花钱
题目来源:
http://www.tyvj.cn/p/1032
https://www.luogu.org/problem/show?pid=2376#sub
https://www.luogu.org/problem/show?pid=2619#sub
题目描述
快 NOIP 了, 国王决定开始每个星期给公主一点零花钱。
国王有一些硬币,一共有 N 种不同的面额。 国王想用给定的硬币的集合,每个星期至少给它某个零花钱的数目 C。请帮国王计算公主最多能支付多少个星期的零花钱。
每一个较小面额的硬币的面额, 都能被 比它面额更大的硬币的面额给整除
输入描述
第 1 行:两个有空格隔开的整数: N 和 C;
第 2 到第 N+1 行:每一行有两个整数表示一个面额的硬币:硬币面额 V
(1 <= V <= 100,000,000)拥有的该面额的硬币数 B (1 <= B <= 1,000,000)。
输出描述
一个单独的整数,表示最多能给支付多少个星期至少为 C 的零用钱。
样例输入
3 6
10 1
1 100
5 120
样例输出
111
数据范围及提示
题目保证给出的面额不重复;
对于 100% 的数据:
1<=N<=20 1<=C<=100000000 1<=Bi<=1000000 1<=Vi<=100000000
题解:
贪心
至少给C元,很显然的是,如果某个硬币的金额大于C,那么直接给,ans+
为了满足更多星期,我们优先使用大的面额且使花的冤枉钱最少;
按照面额大小排序,对于当前面额,在小于等于C的情况下,能放多少就放多少。
某时刻等于C则退出,进行下一次操作。
for循环结束后,如果仍然不能等于C,也就是说,如果要满足,必须大于C,那么为了花费的冤枉钱最少,我们找一个最小值加上。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,c,ans,x,y,tot,minn,tmp;
struct wkw{int v,m;
}a[800];
bool cmp(wkw a,wkw b){return a.v>b.v;
}
int main(){//freopen("money.in","r",stdin);
// freopen("money.out","w",stdout);scanf("%d%d",&n,&c);for(int i=1;i<=n;i++){scanf("%d%d",&x,&y);if(x>=c) {ans+=y;continue;}a[++tot].v=x,a[tot].m=y;}sort(a+1,a+tot+1,cmp);while(1){tmp=c;for(int i=1;i<=tot;i++){if(a[i].m==0) continue;int maxx=min(a[i].m,tmp/a[i].v);a[i].m-=maxx;tmp-=(maxx*a[i].v);if(a[i].m) minn=i;if(tmp==0){ans++;break;}}if(tmp>0){tmp-=a[minn].v;a[minn].m--;if(tmp<=0) ans++;}if(tmp==c) break;}printf("%d",ans);return 0;
}
Problem 2 Oh! My King!
题目来源
http://www.lydsy.com/JudgeOnline/problem.php?id=1087
题目描述
很久很久以前,巨龙未曾出现, 国王风流倜傥京城酒吧鸡王南梦华【雾】 很无聊,他看过叛逆的鲁路修之后感觉国际象棋很好玩, 因此他准备搞一波国际象棋玩耍赛。由于他是国王, 他决定将棋子全换成国王来玩, 并且还是由于 EX 级皇帝特权, 所以他的国王棋子多的一笔,因此他决定在 N×N 的棋盘里面放 K个国王,使他们互不攻击。 又由于他是个乖巧的国王, 是要遵守游戏规则的, 最后他想求共有多少种摆放方案。
游戏规则: 国王能攻击到它上下左右,以及左上、 左下、 右上、 右下八
个方向上附近的各一个格子,共 8 个格子, 要保证国王互不攻击, 如果
没有方案数则输出 0。
国王鸡王南梦华听说你很厉害,决定丢你棋子钦定你干活 23333
输入描述
一行,输入 N 和 K, 意义见上文
输出描述
方案数
样例输入
3 2
样例输出
16
数据范围及提示
对于特殊的 10%的数据, n=1;
对于另 30% 的数据, 1<=n<=3, 1<=k<=n;
对于 100% 的数据,满足 1<= n<=9, 1<= k<=n*n;
题解:
讲了以后就会发现是一道很水的状压DP23333;
和炮兵阵地一样,以行为枚举单位,
预处理出每一行的状态和上下行状态是否合法(对角线上用左移右移即可);
设dp[i][j][pos]为第i行,放了j个国王,状态为pos的方案数
又上一行转移而来
答案是dp[n][k][pos] pos枚举的和(因为最后一行随便什么状态都可以)
没开long long没去文件输入输出流在bzoj上wa了几次。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
bool mmp[600][600];
int sta[600],cnt[600];
long long n,k,maxx,tot;
long long dp[15][100][600];
int find(int x){int ans=0;while(x){if(x&1) ans++;x>>=1;}return ans;
}
void init(){int g=(1<<n);while(g){g--;if(g<<1&g) continue;sta[++tot]=g;cnt[tot]=find(g);}for(int i=1;i<=tot;i++){for(int j=1;j<=tot;j++){mmp[i][j]=mmp[j][i]=((sta[i]&sta[j])|(sta[i]>>1&sta[j])|(sta[i]<<1&sta[j]));}}
}
int main(){scanf("%lld%lld",&n,&k);init();for(int i=1;i<=tot;i++) dp[1][cnt[i]][i]=1;for(int i=2;i<=n;i++){for(int pos=1;pos<=tot;pos++){for(int j=cnt[pos];j<=k;j++){for(int p=1;p<=tot;p++){if(mmp[p][pos]) continue;dp[i][j][pos]+=dp[i-1][j-cnt[pos]][p];}}}}for(int i=1;i<=tot;i++) maxx+=dp[n][k][i];printf("%lld",maxx);return 0;
}
Problem 3 函数求和
题目来源
据说是原创题
题目描述
有一个含有 n 个数字的序列 A, 元素标号 1 到 n。
同时你有 n 个函数,标号为 1 到 n。
第 i 个函数函数值为序列中下标为 Li 到 Ri 的元素和。
现在你需要维护以下两种操作
1 x y : 将序列中下标为 x 的元素修改为 y
2 s t : 询问标号为 s 到 t 的函数值的和
输入描述
第一行一个正整数 n,表示序列和函数的个数。
接下来一行 n 个整数表示序列 A。
接下来 n 行,每行两个整数 Li, Ri,表示第 i 个函数
接下来一行一个整数 q,表示询问次数
下面 q 行,每行一个询问,格式如题面描述
输出描述
对于每个询问 2, 输出对应答案
样例输入
5
1 2 3 4 5
1 3
2 5
4 5
3 5
1 2
4
2 1 4
1 3 7
2 1 4
2 3 5
样例输出
41
53
28
数据范围及提示
对于 20%的数据, n<=100&&q<=100
对于另外 30%数据, Ri–Li<=10,所有 x 各不相同
对于 100%的数据, 1 <=n<=1e5,1<=Li<=Ri<=n, 1<=x<=n,
1<=s<=t<=n,1<=Ai,y<=1e9,1<=q<=1e5;
Problem 4 防 AK 好题
题目来源
bzoj 1017
题目描述
在你的世界中,每个人都有一个能力值, 并且初始为 0
通过金币购买装备,可以提高这一属性,并且不同装备增加的属性值不
同
装备分基础装备和高级装备,基础装备可以直接购买,高级装备需要基础装备合成。 合成高级装备只需要基础装备,不需要附加条件。
一件高级装备可能需要多件不同的基础装备合成,比如 A 的合成可能需要 2 * a && 3 * b && 1 * c。合成高级装备的同时,基础装备消失。
每件基础装备都有一个购买限制以为着你不能无限的购买和合成。
现在你有 m 个金币,你想知道用这些金币最大可以获得多少能力值。
输入描述
第一行两个数字 n, m 分别表示装备种类和金币数
接下来 n 行,按照装备 1 到 n 排序,每行描述一件装备。每行第一个数
字表示这件装备的力量值,接下来一个字符 A || B 表示高级装备||基础
装备。如果是基础装备,接下来两个整数表示单价和数量限制,如果是
高级装备后面一个数字 c 表示这件高级装备需要 c 种低级装备,后面的
2 c 个数分别表示这 c 件装备的种类和需求量。
输出描述
一行一个数字表示能达到的最大能力值
样例输入
10 59
5 A 3 6 1 9 2 10 1
1 B 5 3
1 B 4 3
1 B 2 3
8 A 3 2 1 3 1 7 1
1 B 5 3
5 B 3 3
15 A 3 1 1 5 1 4 1
1 B 3 5
1 B 4 3
样例输出
33
数据范围及提示
对于 100%的数据, N (1 <= n <= 51) m (0 <= m <= 2,000)
对于第 9 测试点时限为 11s, 十个点总时限为 30s
这篇关于10.12 新一波高能胡策题 贪心+状压DP+分块+魔性DP的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!