有一天, 小王同学正走在路上,忽然天上掉下大把大把的馅饼(哈哈哈。。。。)。这个只能说小王同学的人品太好,这馅饼就掉落在他身旁的10米范围内。所以小王同学马上去接馅饼,因为掉在地方的馅饼就不能吃了。他只能在这个10米范围内接馅饼。由于小王同学是一个非常优秀的Oier,但他不是一个优秀的运动员,所以他每秒钟只有在移动不超过一米的范围内接住坠落的馅饼。现在给这条小径如图标上坐标:
为了使问题简化,假设在接下来的一段时间里,馅饼都掉落在0-10这11个位置。开始时小王站在5这个位置上,因此在第一秒,他只能接到4,5,6这三个位置中其中一个位置上的馅饼。问小王最多可能接到多少个馅饼?(假设他的背包可以容纳无穷多个馅饼)
Input
输入数据有多组。每组数据的第一行为以正整数n(0
这道题我看到的第一印象就是FJ接苹果,但一看数据十万就知道一定会T飞,所以必须得换一种思路。根据题意,小王一个单位时间里最多只能走一格,所以我们可以从小到大枚举时间,而当前时间的下一秒的位置,肯定由当前时间往左走、往右走或不动得到。所以就可以递推。
#include
using namespace std;
const int dx[3]={0,1,-1};//不动,往右,往左
const int MAXN=100050;
int n,maxt,dp[11][MAXN],b[11][MAXN],maxn=-MAXN;
inline int read(){
int num=0,f=1;
char c=getchar();
for(;c>'9'||c<'0';c=getchar())
if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())
num=(num<<1)+(num<<3)+c-48;
return num*f;
}
void work(){
maxn=0;
dp[5][0]=0;
b[5][0]=0;//多组数据别忘了清空数组
for(int i=0;ifor(int p=0;p<=10;++p)
if(dp[p][i]>=0){
for(int k=0;k<=2;++k){
int newp=p+dx[k];
if(newp<0||newp>10)continue;//边界
if(b[newp][i+1]<=0)dp[newp][i+1]=max(dp[newp][i+1],dp[p][i]);//当时没有饼掉落
else dp[newp][i+1]=max(dp[p][i]+b[newp][i+1],dp[newp][i+1]);//当时有饼掉落
maxn=max(dp[newp][i+1],maxn);
}
}
}
printf("%d\n",maxn);
}
void init(){
while(1){
n=read();
if(n==0)exit(0);
memset(b,-1,sizeof(b));
memset(dp,-10,sizeof(dp));
for(int i=1;i<=n;++i){
int p=read();
int ti=read();
maxt=max(maxt,ti);
if(b[p][ti]<0)b[p][ti]=0;
b[p][ti]++;
}
work();
}
}
int main(){
init();
return 0;
}
一个蛋糕,可以一次吃一口或一次吃k口,那么问体积为x1~x2不定的蛋糕有多少种吃法。
Input
第一行有两个正整数t,k(1<=t,k<=100000) ,其中t表示数据的组数。
接下来t行,每行两个数x1, x2(1<=x1<=x2<=100000)。
Output
共t行,每行一个正整数x,表示蛋糕数量在x1-x2之间时,一共能有几种不同的吃法,结果对(10^9+7)取模
Sample Input
3 2
1 3
2 3
4 4
Sample Output
6
5
5
这道题很水,只要爬过楼梯就一定会做。需要注意的一点是当k=1时,一次吃一口和一次吃k口是不同的!!!
另外因为有多组数据,为了防止超时,递推出最大的x2的方法数,然后求前缀和,查询区间和时只要sum[x2]-sum[x1-1]就好了。
#include
using namespace std;
const int MAXN=1000000007;
int t,k,x1,x2,dp[100050],ans,maxn,sum[100050];
struct node{
int l,r;
}e[100050];
inline int read(){
int num=0,f=1;
char c=getchar();
for(;c>'9'||c<'0';c=getchar())
if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())
num=(num<<1)+(num<<3)+c-48;
return num*f;
}
void init(){
t=read();k=read();
for(int i=1;i<=t;++i){
e[i].l=read();
e[i].r=read();
maxn=max(maxn,e[i].r);
}
}
void work(){
dp[0]=1;
for(int i=1;i<=maxn;++i){
dp[i]=dp[i-1];
if(i-k>=0)dp[i]+=dp[i-k];
dp[i]%=MAXN;
sum[i]=(sum[i-1]+dp[i])%MAXN;
}
for(int i=1;i<=t;++i){
if(sum[e[i].r]<sum[e[i].l-1])printf("%d\n",sum[e[i].r]+MAXN-sum[e[i].l-1]);//%的意义下做减法要注意先在被减数上加上MAXN防止出现负数
else printf("%d\n",sum[e[i].r]-sum[e[i].l-1]);
}
}
int main(){
init();
work();
return 0;
}
有n个水果, 每个水果都有两个属性值ai表示美味程度, bi表示能量值, 现在要求选出一个或多个水果, 使得选出的水果的ai和与bi和的比例是k 问在这种清形可能出现的情况下ai的和最多是多少, 如果这样的情形不存在输出 -1
Input
第一行包含两个整数n, k (1 ≤ n ≤ 100, 1 ≤ k ≤ 10). 第二行为 n个整数 a1, a2, …, an (1 ≤ ai ≤ 100) — 水果的美味值. 第三行包含水果的能量值。
Output
如果无解输出-1.
否则输出满足条件的ai累加和
Examples
Input
3 2
10 8 1
2 7 1
Output
18
Input
5 3
4 4 4 4 4
2 2 2 2 2
Output
-1
首先这道题不能用搜索,n=100肯定会超时。看到题目中要求让美味值的和最大,所以就想到了背包。但直接背包肯定又做不了,所以我们就转换一下。
根据题意:suma/sumb=k ,所以suma=sumb*k ,所以当背包容量为suma-sumb*k=0时,就是我们要求的最大值。又因为suma-sumb可能是负数,所以将suma-sumb整体偏移p,使得他们都为正,来做数组下标。
#include
using namespace std;
const int p=100000;//偏移量
int n,k,dp[150][200000];
struct node{
int a,b,c;//a为美味值,b为能量值,c为a-b*k;
}e[150];
inline int read(){
int num=0,f=1;
char c=getchar();
for(;c>'9'||c<'0';c=getchar())
if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())
num=(num<<1)+(num<<3)+c-48;
return num*f;
}
void init(){
n=read();k=read();
for(int i=1;i<=n;++i)e[i].a=read();
for(int i=1;i<=n;++i){
e[i].b=read();
e[i].c=e[i].a-e[i].b*k;
}
}
void work(){
memset(dp,-10,sizeof(dp));
dp[0][p]=0;
for(int i=1;i<=n;++i)
for(int j=p*2;j>=e[i].c;--j){
dp[i][j]=max(dp[i-1][j-e[i].c]+e[i].a,dp[i-1][j]);
}
if(dp[n][p]==0)dp[n][p]=-1;
printf("%d",dp[n][p]);
}
int main(){
init();
work();
return 0;
}