题意:从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; }
|
|
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
27 | 28 | 29 | 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 |
|
常用链接
留言簿
随笔分类
随笔档案
搜索
最新评论
阅读排行榜
评论排行榜
|
|