Summer Training #12 Div.2 I(DP)
题意:男猪脚在森林中穿行,依次经过n个商店,每个商店出售vi能量,他能够从每个商店中补充一定能量,能量数值为vi能够整除的最大2次方的次幂,并且要求他从商店购买的能量数值(vi)必须为递增的顺序,问最多能够补充多少能量?
题解:DP
代码(写的非常丑)
#include<stdio.h> #include<string.h> #include<queue> #include<vector> #include<map> using namespace std; #define N 105 int shop[N],d[N][N][2],power[N],en[N],rt,power2[N],ans; int find2(int v){ int k=0; while(!(v%2)){ k++; v/=2; } return k; } int main(){ freopen("C:/Users/fuliujun/Desktop/input.txt","r",stdin); freopen("C:/Users/fuliujun/Desktop/output.txt","w",stdout); int T,i,n,j; scanf("%d",&T); map<int,int>e; while(T--){ e.clear(); scanf("%d",&n); ans=0; for(i=1;i<=n;i++) {scanf("%d",&shop[i]); power[i]=find2(shop[i]); } memset(d,0,sizeof(d)); en[1]=shop[1]; e.insert(pair<int, int>(shop[1],1)); power2[1]=power[1]; rt=1; int flag=1; for(i=2;i<=n;i++){ flag=1; for(j=1;j<=rt;j++) if(shop[i]==en[j]){flag=0;break;} if(flag){ en[++rt]=shop[i]; power2[rt]=power[i]; e.insert(pair<int, int>(shop[i],j)); } } int flagnew[N]; memset(flagnew,0,sizeof(flagnew)); for(i=1;i<=rt;i++)d[0][i][0]=en[i]; for(i=1;i<=n;i++) for(j=1;j<=rt;j++){ if(j==1){ for(int z=1;z<=rt;z++){ d[i][z][0]=d[i-1][z][0]; d[i][z][1]=d[i-1][z][1]; } } int te=e[shop[i]]; if(!flagnew[te]){ d[i][te][1]+=power2[te]; flagnew[te]=1; } if(d[i][j][0]<shop[i]){ d[i][te][1]=max(d[i][j][1]+power2[te],d[i][te][1]); } } for(i=1;i<=rt;i++){ if(d[n][i][1]>ans){ans=d[n][i][1];} } printf("%d\n",ans); } fclose(stdin); fclose(stdout); return 0; }
重新写了一份代码
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int find2(int k){ int temp=0; while(k%2==0){ temp++; k/=2; } return temp; } int main(){ int i,j,T,n,a[105],b[105],f[105]; scanf("%d",&T); while(T--){ scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=find2(a[i]); f[i]=b[i]; } for(i=2;i<=n;i++) for(j=1;j<i;j++){ if(a[j]<a[i])f[i]=max(f[j]+b[i],f[i]); } printf("%d\n",*max_element(f+1,f+n+1)); } return 0; }

浙公网安备 33010602011771号