[编程题] 今天要吃点好的!
加班了一个通宵的度度熊,神经有点恍惚,想到依然未能解决的Bug,眼泪禁不住霹雳哗啦往下掉……他抬头看了看帝都灰蒙蒙的天空,一咬牙,一跺脚,大叫一声——劳资今天要吃点好的! 已知本厂有n个食堂,第i(i属于[1,n])个食堂有m[i]种食物,每种食物有一个价钱c,享受度v,度度熊希望去一个食堂就餐,花费[bot,top]范围内的钱数(也可以拍桌子走人,哪里都不吃了),选择若干种食物,使得自己所能获得的享受度最大。(注意,度度熊还有一个挑食的特点,同一种食物他最多只会点一份。) 现在告诉你所有食堂食物的信息,希望你进行选择搭配,使得度度熊可以得到最大的享受度,并输出这个享受度的值。
输入描述:
第一行是一个正整数T(1<=T<=20),表示有T组测试数据。 对于每组数据—— 第一行是三个数n,bot,top,n代表食堂数1<=n<=10),bot是这次吃饭的最低消费,top是这次吃饭的最高消费(0<=bot,top<=10000) 接下来依次是n个食堂的信息,对于第i个食堂 第一行是一个数m[i](o<=m[i]<=100),代表第i个食堂的食物数 第二行有2*m[i]个数,分别是c[i][1],v[i][1],c[i][2],v[i][2],……c[i][m[i]],v[i][m[i]] c[i][j]表示第i个餐厅第j种食物的价钱,v[i][j]代表第i个餐厅第j种食物给度度熊带来的享受度。
输出描述:
对于每组数据,请输出一行,每行一个正整数。表示度度熊所能获得的最大享受度。 数据结果保证不会超过2^31-1.
输入例子:
2 2 10 20 5 1 1 2 1 5 1 10 1 20 1 5 1 2 2 2 5 2 10 2 20 2 2 10 10 1 5 1 1 5 1
输出例子:
8 0
对每个食堂,做01背包,然后取最大的。
这里是区间[bot,top],所以我们可以通过背恰好重量的东西来解决!
#include<stdio.h>
#include<algorithm>
#include<string.h>
#define LL __int64
using namespace std;
int main()
{
int T,n,bot,top;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&bot,&top);
int m;
int c[105],v[105];
int ans=0,tmp;
for(int i=0;i<n;i++)
{
int f[10005];
//初始化
memset(f,-1,sizeof(f));
f[0]=0;
scanf("%d",&m);
for(int j=0;j<m;j++)
{
scanf("%d%d",&c[j],&v[j]);
}
for(int k=0;k<m;k++)
{
for(int vv=top;vv>=c[k];vv--)
{
if(f[vv]<f[vv-c[k]]+v[k]&&f[vv-c[k]]>=0)//满足恰好背的情况
{
f[vv]=f[vv-c[k]]+v[k];
}
}
}
for(int k=bot;k<=top;k++)
{
ans=max(ans,f[k]);
}
}
printf("%d\n",ans);
}
return 0;
}
我在做的时候,是记录背包的实际重量来想的。
#include<stdio.h>
#include<algorithm>
#define LL __int64
using namespace std;
int main()
{
int T,n,bot,top;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&bot,&top);
int m;
int c[105],v[105];
int ans=0,tmp;
for(int i=0;i<n;i++)
{
int f[10005]={0},w[10005]={0};
scanf("%d",&m);
for(int j=0;j<m;j++)
{
scanf("%d%d",&c[j],&v[j]);
}
for(int k=0;k<m;k++)
{
for(int vv=top;vv>=c[k];vv--)
{
if(f[vv]<f[vv-c[k]]+v[k])
{
f[vv]=f[vv-c[k]]+v[k];
w[vv]=w[vv-c[k]]+c[k];
}
}
}
for(int k=bot;k<=top;k++)
{
if(w[k]>=bot&&w[k]<=top) ans=max(ans,f[k]);
}
}
printf("%d\n",ans);
}
return 0;
}
第二题:
[编程题]01排序
给定一个01串(仅由‘ 0’或‘1’组成的字符串),现在想把这个数字串排序成“非递减”有序序列,请问至少需要多少次交换(任意两个位置交换)?
输入描述:
输入数据第一行是一个正整数T(T<=100),表示有T组测试数据; 接下来的T行,每行给出01串。 数据保证—— 50%的字符串长度在[1,100 ] 95%的字符串长度在[1,10000] 100%的字符串长度在[1,1000000]
输出描述:
对于每组测试数据,请输出排成“非递减有序序列”的最小交换次数。 每组输出占一行。
输入例子:
3 01 10 110
输出例子:
0 1 1
#include<stdio.h>
#include<string.h>
char ch[1000005];
int div[1000005];
int main()
{
int T;
scanf("%d",&T);
getchar();
while(T--)
{
gets(ch);
//puts(ch);
int cnt=0;
int len=strlen(ch);
for(int i=0;i<len;i++)
{
if(ch[i]=='0') div[cnt++]=i;
}
// printf("%d\n",cnt);
if(!cnt||cnt==len) {printf("0\n");continue;}
int ans=0;
for(int i=cnt-1;i>=0;i--)
{
if(div[i]<cnt) break;
if(div[i]>=cnt) ans++;
}
printf("%d\n",ans);
}
return 0;
}