T1:
真心没懂,打了个暴力
T2:
二分少了个=
T3&T4:
我太菜了
其实就是分组背包和BFS而已
水果盛宴(fruit)
题目:
贝茜又再一次地闯入了 F a r m e r Farmer Farmer J o h n John John 的房子!她在厨房发现了一堆柠檬和一堆橘子(每堆都有无限多个),并且,她希望尽可能地多吃。
贝茜的有一个饱腹值上限 T(1<=T<=5,000,000)。吃一个橘子会增加她 A A A 点饱腹值,吃一个柠檬会增加她 B B B 点饱腹值(1<= A A A, B B B<= T T T),如果她愿意,贝茜可以最多喝一次水,这会立即使她的饱腹值变成一半,请你帮助贝茜求出她可以获得的最大饱腹值。
输入:
一行三个整数 T T T, A A A 和 B B B
输出:
一行一个整数,表示贝茜可获得的最大饱腹值
样例:
input
8 5 6
output
8
解题思路:
先做一次完全背包
然后将它们所在格的坐标和所在格坐标除以2或运算一下
再做一遍完全背包
代码:
#include
#include
using namespace std;
int t,a,b,x,y,z,len=2,c=2,l,r,mid;
int f[5000010],m[2600000];
int main()
{
freopen("fruit.in","r",stdin);
freopen("fruit.out","w",stdout);
scanf("%d%d%d",&t,&a,&b);
f[a]=1;
f[b]=1;
for (int i=1;i<=t;i++) //完全背包
{
if (i-a>0)
f[i]=max(f[i-a],f[i]);
if (i-b>0)
f[i]=max(f[i-b],f[i]);
}
for (int i=1;i<=t;i++) //喝水,除2进行或运算
f[i/2]|=f[i];
for (int i=1;i<=t;i++) //再来一次完全背包
{
if (i-a>0)
f[i]=max(f[i],f[i-a]);
if (i-b>0)
f[i]=max(f[i],f[i-b]);
if (f[i]==1)
x=i;
}
cout<<x<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
愤怒的奶牛2(angry)
题目:
贝茜这头奶牛设计了她所认为的下一个热门视频游戏—“愤怒的奶牛”。她认为这是她完全原创的:玩家将一个弹弓射到一个一维的场景中,该场景由位于数字线上各个点的一组干草包组成。每只奶牛都有足够的力量引爆其落地地点附近的干草包,我们的目的是使用一系列奶牛引爆所有的干草包。
有 N N N捆干草包位于这一行的不同整数位置 x x x 1,x2,…,xN,如果一头奶牛以能量 R R R着陆在了数轴上的任意一个位置x,那么会引起半径为 R R R( R R R- x x x… R R R+x)的爆炸,并摧毁范围内的所有干草包。
一共有 K K K头奶牛允许被用来作为炮弹,每头奶牛的能量R都相同。请帮忙决定这个最小的能量,使得用这 K K K头奶牛可以摧毁所有的干草包。
输入:
第一行包含两个整数 N N N, K K K(1<= N N N<=50,000,1<= K K K<=10)
接下来 N N N行,每行包含一个整数 x i xi xi,表示每捆干草包的位置(0<= x i xi xi<=1,000,000,000)
输出:
一行一个整数,表示最少所需要的每头奶牛的能量值 R R R
样例:
input
7 2
20
25
18
8
10
3
1
output
5
解题思路:
二分能量就好
代码:
#include
#include
#include
using namespace std;
int n,m,l,r,mid,x,k;
int a[50010];
int check()
{
x=a[1];
k=0;
for (int i=2;i<=n;i++) //分段,看需要多少头牛
if (a[i]-x>mid*2)
{
k++;
x=a[i];
}
k++;
return k; //返会需要的牛的头数
}
int main()
{
// freopen("angry.in","r",stdin);
// freopen("angry.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
l=1,r=(a[n]-a[1])*2;
while (l<=r)
{
mid=(l+r+1)/2;
if (check()<=m) //少了给右,多了给左
r=mid-1;
else l=mid+1;
}
cout<<l<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
采访(interview)
题目:
你是一名记者,现在要求你去采访 n n n 个国家的领导人。采访每一个国家的领导人需要消耗你的时间为 t t t[ i i i],但你可以收获价值为 v v v[ i i i]的信息,然后就能写成报道……
然而尴尬的是,有一些国家之间的关系属于敌对关系,因此如果一个国家的领导人知道你采访了他的敌对国家领导人,那么他就会拒绝你的采访。总之,你采访的国家中,任意选出一对国家都不能构成敌对关系,你才能够完成你的采访,否则某些部分就要落空。
你的 B o s s Boss Boss他给了你一个时间限制 T T T,如果你在时间限制内没有完成采访任务,你就会被炒鱿鱼。当然,他希望你在时间限制 T T T 内完成的采访累计起来的价值总和最大。
输入:
第一行有三个数,第一个数为时间限制T,第二个数为国家数量n,第三个数为国家之间的敌对组数m。
接下来 n n n 行,每行两个数,第一个数为 t t t[ i i i],第二个数为 v v v[ i i i]。
接下来 m m m 行,每行有 m m m[ i i i]+1 个数,首先输入m[i],表示这一组中一共有多少国家是敌对关系,之后输入m[i]个数,表示这m[i]个国家两两之间为敌对关系(一组敌对关系的国家中,每两个国家都构成敌对关系,比如这一组是1,3,4,那么1 和3,1 和4,3 和4 都构成敌对关系),若 m m m[ i i i] = 1,那么这个国家与其他国家都不构成敌对关系。
输出:
一个整数,表示最大价值 V V V。
样例:
input
10 5 2
5 10
7 9
6 3
1 13
8 1
3 1 3 4
2 2 5
output
22
数据范围限制:
60%的数据: m m m=1;
100%的数据:0≤ T T T≤50000,0≤ n n n≤500,1≤ m m m≤10, n n n=∑ m m m[ i 4 ] , 即 i4],即 i4],即m [ 1 ] + [1]+ [1]+m [ 2 ] + . . . . . = [2]+.....= [2]+.....=n$,且敌对关系中每个国家编号只会出现一次。
解题思路:
分组背包模板套一套
二维的哈
代码:
#include
#include
#include
using namespace std;
int n,d,m,t[520],q[520],a[12][120],f[520][50010];
int main()
{
freopen("interview.in","r",stdin);
freopen("interview.out","w",stdout);
scanf("%d%d%d",&d,&n,&m);
for (int i=1;i<=n;i++)
scanf("%d%d",&t[i],&q[i]);
for (int i=1;i<=m;i++)
{
scanf("%d",&a[i][1]);
for (int j=1;j<=a[i][1];j++)
scanf("%d",&a[i][j+1]);
}
for (int i=1;i<=m;i++)
{
for (int j=1;j<=d;j++)
f[i][j]=f[i-1][j];
for (int j=2;j<=a[i][1]+1;j++)
for (int k=d;k>=t[a[i][j]];k--)
f[i][k]=max(f[i][k],f[i-1][k-t[a[i][j]]]+q[a[i][j]]);
}
cout<<f[m][d]<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
房间开灯(light)
题目:
F a r m e r Farmer Farmer J o h n John John 最近正在修建一个巨大的包含 N N N× N N N 个房间的牲口棚,这些房间从(1,1)标号到( N N N, N N N)。由于某些原因而害怕黑暗,贝茜这头奶牛想要尽可能地开更多房间的灯。贝茜从房间(1,1)出发,这个房间是唯一一个一开始就亮着的房间。在一些房间中,她会找到一些电灯开关,这些开关她可以用来切换其他房间的灯的状态。比如,在(1,1)这个房间中可能存在一个电灯开关来控制(1,2)房间中的电灯。贝茜只能进电灯开着的房间,并且贝茜只能从房间( x x x, y y y)走到四个方向的房间( x x x-1, y y y),( x x x+1, y y y),( x x x, y y y-1)和( x x x, y y y+1)(如果在边界的话,那可能会更少)。请帮忙统计贝茜最多可以照亮多少房间。
输入:
第一行两个整数 N N N, M M M(2<= N N N<=100,1<= M 4 < = 20 , 000 ) 下 面 4 M M4<=20,000) 下面 4M M4<=20,000)下面4M 行,每行用四个整数 x x x, y y y, a a a, b b b 来表示房间( x x x, y y y)存在着可以控制房间( a a a, b b b)的灯的开关。一个房间可能有多个开关,一个房间的灯的开关可能存在于多个房间中。
输出:
一行一个整数,表示贝茜最多可以照亮的房间数
样例:
3 6
1 1 1 2
2 1 2 2
1 1 1 3
2 3 3 1
1 3 1 2
1 3 2 1
output
5
提示:
在这个样例中,贝茜可以使用房间(1,1)内的开关打开房间(1,2)和(1,3)的灯。然后她可以走到(1,3),使用(1,3)内的开关打开(2,1)的灯,接着可以通过(2,1)打开(2,2)的灯,然而(2,3)是黑暗的,她无法去打开(2,3)房间里的开关,因此,她最多只能打开 5个房间里的灯。
解题思路:
将BFS改一下
前面用邻接表将此房间内存的开灯按钮所有都打开
代码:
#include
#include
using namespace std;
struct hhx{
int x,y,next;
}a[20010];
int f[20010][2],p[120][120],m[120][120],head[120][120];
int fx[5]={0,0,0,1,-1},fy[5]={0,1,-1,0,0};
int n,k,x,y,x1,y1,t,h,ma;
int main()
{
freopen("light.in","r",stdin);
freopen("light.out","w",stdout);
scanf("%d%d",&n,&k);
for (int i=1;i<=k;i++)
{
scanf("%d%d%d%d",&x,&y,&x1,&y1);
a[i].x=x1;
a[i].y=y1;
a[i].next=head[x][y];
head[x][y]=i;
}
t=1;
p[1][1]=1;
f[1][1]=1;
f[1][2]=1;
m[1][1]=1;
do{
h++;
int i=head[f[h][1]][f[h][2]];
while (i>0) //开灯
{
m[a[i].x][a[i].y]=1;
i=a[i].next;
}
for (int j=1;j<=h;j++) //普通的bfs
{
for (int i=1;i<=4;i++)
{
int xx=f[j][1]+fx[i],yy=f[j][2]+fy[i];
if (xx>0&&x<=n&&y>0&&y<=n&&p[xx][yy]==0&&m[xx][yy]==1)
{
p[xx][yy]=1;
f[++t][1]=xx;
f[t][2]=yy;
}
}
}
}while (h<t);
for (int i=1;i<=n;i++) //找开了的灯
for (int j=1;j<=n;j++)
if (m[i][j]==1)
ma++;
cout<<ma<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}