题意:从n根筷子中选出3*(k+8)根筷子,组成k+8组,每组3根,每组的badness值为最短两根长度之差的平方。求最小的badness值。 分析:这本是个很简单的题,但我一直脑残总想着顺推,想了各种方法处理第三根筷子,发现都不行。其实逆着推就可以保证每组都能找到最长的那根筷子了。 dp[i][j]表示从第i根到第n根组成了j组的最小值,则有dp[i][j]=min(dp[i+1][j],dp[i+2][j-1]+(a[i+1]-a[i])*(a[i+1]-a[i]))。注意当n-i+1==3*j时,dp[i][j]是直接等于dp[i+2][j-1]+(a[i+1]-a[i])*(a[i+1]-a[i])的,因为这时不能再舍弃第i根筷子不用了。
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
#define min(a,b) ((a)<(b)?(a):(b))
#define inf 2000000000

int dp[5010][1010],n,k,a[5010];

int main()
  {
int t,i,j;
scanf("%d",&t);
while(t--)
 {
scanf("%d%d",&k,&n);
k+=8;
for(i=1;i<=n;i++) scanf("%d",a+i);
for(i=n;i>=1;i--) dp[i][0]=0;
for(i=n;i>=n-1;i--) // 初始化
 {
for(j=1;j<=k;j++) dp[i][j]=inf;
}
for(i=n-2;i>=1;i--)
 {
for(j=1;j<=k&&n-i+1>=3*j;j++)
 {
if(n-i+1>3*j) dp[i][j]=min(dp[i+1][j],dp[i+2][j-1]+(a[i+1]-a[i])*(a[i+1]-a[i]));
else dp[i][j]=dp[i+2][j-1]+(a[i+1]-a[i])*(a[i+1]-a[i]);
}
}
printf("%d\n",dp[1][k]);
}
return 0;
}
题意:给出m个长度为3的由0~9组成的字符串,每个字符串有一个权值,可正可负。要求构造出一个长度为n的字符串,若字符串中包含题目给出的某个字符串,则获得该字符串的权值。求一个权值最大的字符串。 分析:其实很早就想到了记录当前位和上一位的数字的dp方程,但是由于没理解题目意思(貌似题目说的也不太清楚),所以不确定如果包含同一个字符串多次,该字符串的权值是只算一次还是算多次。在网上看了看他人的解答,原来是按算多次来理解的。于是下手写,细想的时候发现顺推不能保证字典序最小,于是加了个string记录,还是顺推,果断超时了。才想到从右往左倒着dp,就能保证最后得出的字符串是字典序最小的了,这一点想一想dp时循环的顺序就很容易理解了。 用f[now][i][j]表示从右往左到第now位,且第now位上数字为i,第now-1位上的数字为j的最大值,则f[now][i][j]=max{ f[now-1][j][k]+w[100*i+10*j+k] }
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <limits.h>
using namespace std;
#define inf INT_MAX

int f[10010][10][10],pre[10010][10][10],n,m,w[1010],out[10010];

int main()
  {
int i,j,k,ans,p,q,tem,x,y,now;
while(scanf("%d%d",&m,&n)!=EOF)
 {
memset(w,0,sizeof(w));
for(i=1;i<=m;i++)
 {
scanf("%d%d",&x,&y);
w[x]=y;
}
for(j=0;j<=9;j++)
 {
for(k=0;k<=9;k++)
 {
f[2][j][k]=0;
}
}
for(now=3;now<=n;now++) // dp
 {
for(i=0;i<=9;i++)
 {
for(j=0;j<=9;j++)
 {
f[now][i][j]=-inf;
for(k=0;k<=9;k++)
 {
if(f[now-1][j][k]+w[100*i+10*j+k]>f[now][i][j])
 {
f[now][i][j]=f[now-1][j][k]+w[100*i+10*j+k];
pre[now][i][j]=k;
}
}
}
}
}
ans=-inf;
for(i=0;i<=9;i++)
 {
for(j=0;j<=9;j++)
 {
if(f[n][i][j]>ans)
 {
ans=f[n][i][j];
p=i; q=j;
}
}
}
i=n;
while(i>2)
 {
printf("%d",p);
tem=pre[i][p][q];
p=q; q=tem;
i--;
}
printf("%d%d\n",p,q);
}
return 0;
}
题意:表达能力不好,就不说了。 分析:算是比较简单的背包了,f[i][j][k]表示前i辆车装了j个武器1和k个武器2后还能装武器3的最多个数,再转移即可。
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))

int f[2][510][510],w[4],s[4],d[4],x[110],y[110],n;

int main()
  {
int i,j,k,now,pre,tem,c1,c2,c3,d4,ca=0,p,q,rew,res;
int last1,last2,up1,up2;
while(scanf("%d",&n)&&n)
 {
if(ca>0) printf("\n");
for(i=1;i<=3;i++) scanf("%d%d%d",&w[i],&s[i],&d[i]);
scanf("%d%d%d%d",&c1,&c2,&c3,&d4);
for(i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
memset(f,-1,sizeof(f));
f[0][0][0]=0;
now=1; pre=0;
last1=0; last2=0;
for(i=1;i<=n;i++)
 {
up1=last1+min(x[i]/w[1],y[i]/s[1]); // 加点小优化减少决策范围 从5000ms减到500ms
if(up1>500) up1=500;
up2=last2+min(x[i]/w[2],y[i]/s[2]);
if(up2>500) up2=500;
for(j=0;j<=up1;j++)
 {
for(k=0;k<=up2;k++)
 {
f[now][j][k]=-1;
for(p=0;p<=j;p++)
 {
if(p*w[1]>x[i]||p*s[1]>y[i]) break;
for(q=0;q<=k;q++)
 {
if(p*w[1]+q*w[2]>x[i]||p*s[1]+q*s[2]>y[i]) break;
if(f[pre][j-p][k-q]==-1) continue;
rew=x[i]-p*w[1]-q*w[2];
res=y[i]-p*s[1]-q*s[2];
tem=min(rew/w[3],res/s[3]); // 当前这辆车装完p个武器1和q个武器2后还能装武器3的个数
if(f[pre][j-p][k-q]+tem>f[now][j][k])
f[now][j][k]=f[pre][j-p][k-q]+tem;
}
}
if(f[now][j][k]!=-1)
 {
last1=max(last1,j);
last2=max(last2,k);
}
}
}
tem=now; now=pre; pre=tem;
}
int flag,ans=0,num;
if(c1*d[1]+c2*d[2]+c3*d[3]>d4) flag=1; // 选择比较好的组合武器的方式
else flag=2;
for(i=0;i<=500;i++)
 {
for(j=0;j<=500;j++)
 {
if(f[pre][i][j]==-1) continue;
k=f[pre][i][j];
if(flag==1)
ans=max(ans,i*d[1]+j*d[2]+k*d[3]);
else
 {
num=min(i/c1,min(j/c2,k/c3));
tem=num*d4+(i-num*c1)*d[1]+(j-num*c2)*d[2]+(k-num*c3)*d[3];
ans=max(ans,tem);
}
}
}
printf("Case %d: %d\n",++ca,ans);
}
return 0;
}
|
|
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
30 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|
常用链接
留言簿
随笔分类
随笔档案
搜索
最新评论

阅读排行榜
评论排行榜
|
|