【碎碎念】今天拼了一下午的积木花,送我一朵小红花
0-1 Knapsack Problem
问题
你有N件东西,你想把它们放进背包里。物品i的价值vi和重量wi。
您希望找到一个项目的子集,以便:这些物品的总价值要尽可能的大。这些物品的总重量最多为W,也就是背包的容量。找出背包中物品的最大总价值。
输入
N W
v1 w1
v2 w2
:
vN wN
第一行由整数N和w组成。在接下来的几行中,给出第i项的值和权重。输出
打印一行中项目的最大总价值。约束
1≤n≤100
1≤vi≤1000
1≤wi≤1000
1≤w≤10000
输入1
4个5
4个2
5个2
2 1
8 3
示例输出1
13样本输入2
2 20
思路
与第一套的第四题类似,代码无改变
只是输入w和d的位置有所改变
代码
#include <stdio.h>
int main(){
//第一行输入 两个空格分隔的整数
int n,m;
scanf("%d %d",&n,&m) ;
//定义状态
int dp[12881] ;
//初始化dp[i]=0
for(int i=0;i<=m;i++){
dp[i]=0;
}
//转移方程
for(int i=1;i<=n;i++) {//注意 i=1
//定义重量和价值 两个空格分隔的整数描述魅力i: W i和D i
int w,d;
scanf("%d %d",&d,&w) ;//更改输入位置
for(int j=m;j>=w;j--){//注意j>=w
if(dp[j-w]+d>dp[j])
dp[j]=dp[j-w]+d;
}
}
printf("%d\n",dp[m]);
return 0;
}
#include <stdio.h>
int main(){
//第一行输入 两个空格分隔的整数
int n,m;
scanf("%d %d",&n,&m) ;
//定义状态
int dp[10001] ;
//初始化dp[i]=0
for(int i=0;i<=m;i++){
dp[i]=0;
}
//转移方程
for(int i=1;i<=n;i++) {//注意 i=1
//定义重量和价值 两个空格分隔的整数描述魅力i: W i和D i
int w[101],d[101];//更改为数组类型
scanf("%d %d",&d[i],&w[i]) ;//输入改变
for(int j=m;j>=w[i];j--){//注意j>=w
if(dp[j-w[i]]+d[i]>dp[j])
dp[j]=dp[j-w[i]]+d[i];
}
}
printf("%d\n",dp[m]);
return 0;
}
Election Time
问题
奶牛们在推翻了暴君农场主约翰后进行了第一次选举,贝茜是N头奶牛(1≤N≤50000头)竞选总统之一。然而,在选举真正开始之前,贝西想确定谁最有可能获胜。
选举包括两轮。在第一轮中,获得最多票数的K头奶牛(1≤K≤N)进入第二轮。在第二轮投票中,得票最多的奶牛成为总统。
假设奶牛i预计在第一轮获得Ai票(1≤Ai≤1000,000,000),在第二轮获得Bi票(1≤Bi≤1000,000,000)(如果它成功了),确定哪头奶牛预计会赢得选举。值得庆幸的是,Ai列表中没有出现两次投票计数;同样,在Bi名单中没有出现两次投票计数。
输入
*第一行:两个空格分隔的整数:N和K
*第2行…N+1:第i+1行包含两个空格分隔的整数:Ai和Bi输出
*第一行:预计将赢得选举的牛的指数。
思路
选举两轮-->双重循环
题目意思,一些牛进行竞选,竞选两次,第一次有K只牛入围,第二次竞选从入围的牛进行竞选第一名。
思路,改进快速排序,进行两次即可,不多说了具体代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
// 定义结构体node,包含任务的两个属性a、b及任务编号num
struct node
{
int a, b, num;
} s[50010];
// 比较函数cmpa,按a降序,若a相同则按b降序
int cmpa(node a, node b)
{
if (a.a == b.a) return a.b > b.b; // a相同时比较b
return a.a > b.a; // 直接比较a
}
// 比较函数cmpb,仅按b降序
int cmpb(node a, node b)
{
if (a.b == b.b) return a.a > b.a; // b相同时比较a
return a.b > b.b; // 直接比较b
}
int main()
{
int i, n, k;
// 循环读取输入,直到文件结束
while (scanf("%d%d", &n, &k) != EOF)
{
// 读取n个任务的属性a和b
for (i = 0; i < n; ++i)
{
scanf("%d%d", &s[i].a, &s[i].b);
s[i].num = i + 1; // 记录任务编号
}
// 首先按属性a降序排序所有任务
sort(s, s + n, cmpa);
// 然后在前k个任务中按属性b降序排序
sort(s, s + k, cmpb);
// 输出排序后的前k个任务中a属性最大任务的编号
printf("%d\n", s[0].num);
}
return 0;
}
代码
#include <cstdio>
#include <algorithm>
using namespace std;
struct node
{
int a,b,num;
} s[50010];
int cmpa(node a, node b)
{
if (a.a == b.a) return a.b > b.b;
return a.a > b.a;
}
int cmpb(node a, node b)
{
if (a.b == b.b) return a.a > b.a;
return a.b > b.b;
}
int main()
{
int i,n,k;
while (scanf("%d%d", &n, &k) != EOF)
{
for (i = 0; i < n; ++i)
{
scanf("%d%d", &s[i].a, &s[i].b);
s[i].num = i + 1;
}
sort(s, s + n, cmpa);
sort(s, s + k, cmpb);
printf("%d\n", s[0].num);
}
return 0;
}
寒冰王座
代码
注意大于小于
#include<stdio.h>
int main(){
int t;
scanf("%d",&t) ;
for(int i=0;i<t;i++){
int n;
scanf("%d",&n);
int ans=0;
if(n>=300) ans=n%50;
else if(n>=200&&n<300) ans=n-200;
else if(n>=150&&n<200) ans=n-150;
else if (n<150)ans=n;
printf("%d\n",ans);
}
return 0;
}
Charm Bracelet
代码
与0-1一样 (ACM实训0-1背包问题70%可能性必考)
#include<stdio.h>
int main(){
int n,m;
int dp[12881];
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++){
dp[i]=0;
}
for(int i=1;i<=n;i++){
int w,d;
scanf("%d %d",&w,&d);
for(int j=m;j>=w;j--){
if(dp[j-w]+d>dp[j])
dp[j]=dp[j-w]+d;
}
}
printf("%d\n",dp[m]);
return 0;
}
Anton and Letters
代码
#include<stdio.h>
int main(){
int flag[26];
for(int i=0;i<26;i++){
flag[i]=0;
}
char tmp;
while(tmp!='}'){
scanf("%c",&tmp);
if(tmp=='}') break;
if(tmp<='z'&&tmp>='a'){
flag[tmp-'a']++;
}
}
int cnt=0;
for(int i=0;i<26;i++){
if(flag[i]>0) cnt++;
}
printf("%d",cnt);
return 0;
}
Sum of Digits
代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char s[100000];
int result = 0;
int sum = 0;
int main(){
scanf("%s",&s);
while(1){
if(strlen(s)==1)
break;
sum=0;
for(int i=0;i < strlen(s); i++){
sum+=s[i]-'0';
}
itoa(sum ,s ,10);
result++;
}
printf("%d",result);
return 0;
}