第六周 10.4-10.10
10.4
CF 582A GCD Table
贪心取最大。熟悉set大法。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <set> 7 using namespace std; 8 multiset<int> S; 9 multiset<int>::iterator it; 10 vector<int> ans; 11 12 int gcd(int a,int b) 13 { 14 return a%b?gcd(b,a%b):b; 15 } 16 17 int main(void) 18 { 19 S.clear(); 20 int n; scanf("%d",&n); 21 for(int i=0;i<n*n;i++) 22 { 23 int x; 24 scanf("%d",&x); 25 S.insert(x); 26 } 27 while(!S.empty()) 28 { 29 it=S.end(); it--; 30 int cur=*it; 31 S.erase(it); 32 for(int i=0;i<ans.size();i++) 33 { 34 int t=gcd(ans[i],cur); 35 for(int i=0;i<2;i++) 36 { 37 it=S.find(t); 38 S.erase(it); 39 } 40 } 41 ans.push_back(cur); 42 } 43 for(int i=0;i<ans.size();i++) printf("%d ",ans[i]); 44 puts(""); 45 return 0; 46 }
HDU 3713 Double Maze
BFS。手写队列保存前驱输出路径。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 bool vis[7][7][7][7]; 7 int G[21][7][7]; 8 9 struct node 10 { 11 int x1,y1,x2,y2; 12 char op; 13 int pre; 14 }p[2000]; 15 16 bool f(int op,int i,int j,int x) 17 { 18 return G[op][i][j]&(1<<(x-1)); 19 } 20 21 void ans_print(int pos) 22 { 23 if(p[pos].pre) ans_print(p[pos].pre); 24 putchar(p[pos].op); 25 return; 26 } 27 28 int main(void) 29 { 30 int T; cin>>T; 31 for(int i=1;i<=6;i++) for(int j=1;j<=6;j++) scanf("%d",&G[0][i][j]); 32 for(int t=1;t<T;t++) 33 { 34 int xs1,ys1,xs2,ys2,xt1,yt1,xt2,yt2; 35 for(int i=1;i<=6;i++) for(int j=1;j<=6;j++) 36 { 37 scanf("%d",&G[t][i][j]); 38 if(f(t-1,i,j,6)){xs1=i;ys1=j;} 39 if(f(t,i,j,6)){xs2=i;ys2=j;} 40 if(f(t-1,i,j,7)){xt1=i;yt1=j;} 41 if(f(t,i,j,7)){xt2=i;yt2=j;} 42 } 43 int cnt=0,start=-1,ans=-1; 44 memset(vis,0,sizeof(vis)); 45 p[0].x1=xs1,p[0].y1=ys1,p[0].x2=xs2,p[0].y2=ys2; 46 vis[xs1][ys1][xs2][ys2]=1; 47 while(start<cnt) 48 { 49 int pos=++start; 50 int x1=p[pos].x1,y1=p[pos].y1,x2=p[pos].x2,y2=p[pos].y2; 51 if(x1==xt1&&y1==yt1&&x2==xt2&&y2==yt2) {ans=pos; break;} 52 if((f(t-1,x1,y1,2)||(x1<6&&f(t-1,x1+1,y1,5)))&&(f(t,x2,y2,2)||(x2<6&&f(t,x2+1,y2,5)))) 53 { 54 int xx1=x1+(f(t-1,x1,y1,2)?0:1),xx2=x2+(f(t,x2,y2,2)?0:1); 55 if(!vis[xx1][y1][xx2][y2]) 56 { 57 cnt++; 58 p[cnt].x1=xx1,p[cnt].y1=y1,p[cnt].x2=xx2,p[cnt].y2=y2; 59 p[cnt].op='D',p[cnt].pre=pos; 60 vis[xx1][y1][xx2][y2]=1; 61 } 62 } 63 if((f(t-1,x1,y1,1)||(y1>1&&f(t-1,x1,y1-1,5)))&&(f(t,x2,y2,1)||(y2>1&&f(t,x2,y2-1,5)))) 64 { 65 int yy1=y1-(f(t-1,x1,y1,1)?0:1),yy2=y2-(f(t,x2,y2,1)?0:1); 66 if(!vis[x1][yy1][x2][yy2]) 67 { 68 cnt++; 69 p[cnt].x1=x1,p[cnt].y1=yy1,p[cnt].x2=x2,p[cnt].y2=yy2; 70 p[cnt].op='L',p[cnt].pre=pos; 71 vis[x1][yy1][x2][yy2]=1; 72 } 73 } 74 if((f(t-1,x1,y1,3)||(y1<6&&f(t-1,x1,y1+1,5)))&&(f(t,x2,y2,3)||(y2<6&&f(t,x2,y2+1,5)))) 75 { 76 int yy1=y1+(f(t-1,x1,y1,3)?0:1),yy2=y2+(f(t,x2,y2,3)?0:1); 77 if(!vis[x1][yy1][x2][yy2]) 78 { 79 cnt++; 80 p[cnt].x1=x1,p[cnt].y1=yy1,p[cnt].x2=x2,p[cnt].y2=yy2; 81 p[cnt].op='R',p[cnt].pre=pos; 82 vis[x1][yy1][x2][yy2]=1; 83 } 84 } 85 if((f(t-1,x1,y1,4)||(x1>1&&f(t-1,x1-1,y1,5)))&&(f(t,x2,y2,4)||(x2>1&&f(t,x2-1,y2,5)))) 86 { 87 int xx1=x1-(f(t-1,x1,y1,4)?0:1),xx2=x2-(f(t,x2,y2,4)?0:1); 88 if(!vis[xx1][y1][xx2][y2]) 89 { 90 cnt++; 91 p[cnt].x1=xx1,p[cnt].y1=y1,p[cnt].x2=xx2,p[cnt].y2=y2; 92 p[cnt].op='U',p[cnt].pre=pos; 93 vis[xx1][y1][xx2][y2]=1; 94 } 95 } 96 } 97 if(ans<0) printf("-1"); 98 else if(ans>0) ans_print(ans); 99 puts(""); 100 } 101 return 0; 102 }
10.5
POJ 3573 I18n
set大法。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <set> 6 using namespace std; 7 char s[200]; 8 9 struct node 10 { 11 char l,r; 12 int mid; 13 bool ok; 14 char word[100]; 15 friend bool operator < (node x,node y) 16 { 17 if(x.l!=y.l) return x.l<y.l; 18 if(x.mid!=y.mid) return x.mid<y.mid; 19 return x.r<y.r; 20 } 21 }; 22 set<node> S; 23 set<node>::iterator it; 24 25 bool is_alp(char c) 26 { 27 return (c>='a'&&c<='z') || (c>='A'&&c<='Z'); 28 } 29 30 bool is_num(char c) 31 { 32 return c>='0'&&c<='9'; 33 } 34 35 char lower(char c) 36 { 37 return (c<='Z')?(c+32):c; 38 } 39 40 char upper(char c) 41 { 42 return (c>='a')?(c-32):c; 43 } 44 45 int main(void) 46 { 47 while(gets(s)) 48 { 49 int len=strlen(s); 50 for(int i=0;i<len;i++) 51 { 52 if(is_alp(s[i])) 53 { 54 if(i==len-1) putchar(s[i]); 55 else if(is_alp(s[i+1])) 56 { 57 int L=0; 58 while(i+L<len && is_alp(s[i+L])) L++; 59 if(L==2||L==3) {putchar(s[i]); continue;} 60 node tmp; 61 tmp.l=lower(s[i]); 62 tmp.r=lower(s[i+L-1]); 63 tmp.mid=L-2; 64 tmp.ok=1; 65 for(int j=0;j<L;j++) tmp.word[j]=lower(s[i+j]); 66 tmp.word[L]=0; 67 if((it=S.find(tmp))!=S.end()) 68 { 69 if((*it).ok&&strcmp((*it).word,tmp.word)!=0) 70 { 71 S.erase(it); 72 tmp.ok=0; 73 S.insert(tmp); 74 } 75 } 76 else S.insert(tmp); 77 for(int j=0;j<L;j++) putchar(s[i+j]); 78 i+=L-1; 79 } 80 else if(is_num(s[i+1])) 81 { 82 int L; 83 node tmp; 84 tmp.l=lower(s[i]); 85 if(is_num(s[i+2])) 86 { 87 tmp.mid=10*(s[i+1]-'0')+s[i+2]-'0'; 88 tmp.r=lower(s[i+3]); 89 L=4; 90 } 91 else 92 { 93 tmp.mid=s[i+1]-'0'; 94 tmp.r=lower(s[i+2]); 95 L=3; 96 } 97 if((it=S.find(tmp))!=S.end()&&(*it).ok) 98 { 99 int type=(s[i]<='Z')+(s[i+L-1]<='Z'); 100 int L=strlen((*it).word); 101 if(type==0) for(int j=0;j<L;j++) putchar((*it).word[j]); 102 else if(type==1) 103 { 104 putchar(upper((*it).word[0])); 105 for(int j=1;j<L;j++) putchar((*it).word[j]); 106 } 107 else for(int j=0;j<L;j++) putchar(upper((*it).word[j])); 108 } 109 else for(int j=0;j<L;j++) putchar(s[i+j]); 110 i+=L-1; 111 } 112 else putchar(s[i]); 113 } 114 else putchar(s[i]); 115 } 116 puts(""); 117 } 118 return 0; 119 }
POJ 3974 Palindrome
重贴板。温习manacher。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn=1001000; 7 char s[maxn],b[2*maxn],E[]="END"; 8 int p[2*maxn]; 9 10 int main(void) 11 { 12 int kase=0; 13 while(~scanf("%s",s)) 14 { 15 if(strcmp(s,E)==0) break; 16 int m=strlen(s),len=2*m+1; 17 b[0]='!'; b[len+1]='@'; 18 b[len]='#'; 19 for(int i=0;i<m;i++) 20 { 21 b[2*i+2]=s[i]; 22 b[2*i+1]='#'; 23 } 24 int mx=0,id; 25 for(int i=1;i<=len;i++) 26 { 27 if(mx>i) p[i]=min(p[2*id-i],mx-i); 28 else p[i]=1; 29 while(b[i+p[i]]==b[i-p[i]]) p[i]++; 30 if(p[i]+i>mx) {mx=p[i]+i; id=i;} 31 } 32 int M=0; 33 for(int i=1;i<=len;i++) M=max(M,p[i]); 34 printf("Case %d: %d\n",++kase,M-1); 35 } 36 return 0; 37 }
HDU 5413 吉哥系列故事――完美队形II
吐槽题名。先manacher再处理下连续单调个数。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn=101000; 7 int b[2*maxn],p[2*maxn]; 8 int inc[maxn],des[maxn]; 9 10 int main(void) 11 { 12 int T; cin>>T; 13 while(T--) 14 { 15 int n; scanf("%d",&n); 16 int len=2*n+1; 17 b[0]=-1; b[len+1]=-2; 18 b[len]=-3; 19 for(int i=0;i<n;i++) 20 { 21 scanf("%d",b+2*i+2); 22 b[2*i+1]=-3; 23 } 24 int mx=0,id; 25 for(int i=1;i<=len;i++) 26 { 27 if(mx>i) p[i]=min(p[2*id-i],mx-i); 28 else p[i]=1; 29 while(b[i+p[i]]==b[i-p[i]]) p[i]++; 30 if(p[i]+i>mx) {mx=p[i]+i; id=i;} 31 } 32 inc[1]=des[n]=1; 33 for(int i=2;i<n;i++) inc[i]=(b[2*i]>=b[2*i-2])?(inc[i-1]+1):1; 34 for(int i=n-1;i>0;i--) des[i]=(b[2*i]>=b[2*i+2])?(des[i+1]+1):1; 35 int ans=0; 36 for(int i=1;i<=len;i++) 37 { 38 int tmp; 39 if(i%2==0) tmp=min(p[i]-1,2*min(inc[i/2],des[i/2])-1); 40 else tmp=min(p[i]-1,2*min(inc[i/2],des[i/2+1])); 41 ans=max(ans,tmp); 42 } 43 printf("%d\n",ans); 44 } 45 return 0; 46 }
HDU 3294 Girls' research
水manacher。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn=201000; 7 char a[5],s[maxn],b[2*maxn]; 8 int p[2*maxn]; 9 10 char f(char c) 11 { 12 c=c-a[0]+'a'; 13 if(c<'a') c+=26; 14 return c; 15 } 16 17 int main(void) 18 { 19 while(~scanf("%s",a)) 20 { 21 scanf("%s",s); 22 int m=strlen(s),len=2*m+1; 23 b[0]='!'; b[len+1]='@'; 24 b[len]='#'; 25 for(int i=0;i<m;i++) 26 { 27 b[2*i+2]=s[i]; 28 b[2*i+1]='#'; 29 } 30 int mx=0,id; 31 for(int i=1;i<=len;i++) 32 { 33 if(mx>i) p[i]=min(p[2*id-i],mx-i); 34 else p[i]=1; 35 while(b[i+p[i]]==b[i-p[i]]) p[i]++; 36 if(p[i]+i>mx) {mx=p[i]+i; id=i;} 37 } 38 int M=0,pos; 39 for(int i=1;i<=len;i++) 40 if(p[i]-1>M) {M=p[i]-1; pos=i;} 41 if(M<=1) puts("No solution!"); 42 else 43 { 44 printf("%d %d\n",(pos-p[pos]+2)/2-1,(pos+p[pos]-2)/2-1); 45 for(int i=pos-p[pos]+2;i<=pos+p[pos]-2;i+=2) putchar(f(b[i])); 46 puts(""); 47 } 48 } 49 return 0; 50 }
HDU 4763 Theme Section
exkmp。暴力一下。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 using namespace std; 6 # define maxn 1000010 7 int m,Next[maxn]; 8 char b[maxn]; 9 10 void getNext(void) 11 { 12 int P=1,j; Next[0]=m; 13 for(int i=Next[1]=0;i<m-1&&b[i]==b[i+1];) Next[1]=++i; 14 for(int i=2;i<m;i++) 15 { 16 if(Next[i-P]+i<Next[P]+P) Next[i]=Next[i-P]; 17 else 18 { 19 j=max(Next[P]+P-i,0); 20 while(i+j<m&&b[j]==b[j+i]) j++; 21 Next[i]=j; P=i; 22 } 23 } 24 return; 25 } 26 27 int main(void) 28 { 29 int T; cin>>T; 30 while(T--) 31 { 32 scanf("%s",b); 33 m=strlen(b); 34 getNext(); 35 int ans=0; 36 for(int i=1;i<=m/3;i++) 37 { 38 if(Next[m-i]!=i) continue; 39 int ok=0; 40 for(int j=i;j<=m-2*i;j++) 41 if(Next[j]>=i) {ok=1;break;} 42 if(ok) ans=i; 43 } 44 printf("%d\n",ans); 45 } 46 return 0; 47 }
终于切完1个月前开的一版。其实到最后根本不想做了。
10.6
POJ 1200 Crazy Search
题目都没给范围阿。哈希还是不怎么懂- -
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 bool Hash[16000000]; 6 char s[10000000]; 7 int c[256]; 8 9 int main(void) 10 { 11 int N,NC; 12 scanf("%d%d%s",&N,&NC,s); 13 int cnt=0,len=strlen(s); 14 if(N>len) {puts("0");return 0;} 15 for(int i=0;i<len;i++) 16 { 17 if(!c[s[i]]) c[s[i]]=++cnt; 18 if(cnt==NC) break; 19 } 20 int sum=0,tmp=1; 21 for(int i=0;i<N;i++) 22 { 23 sum=sum*NC+c[s[i]]-1; 24 tmp*=NC; 25 } 26 tmp/=NC; Hash[sum]=1; 27 int ans=1; 28 for(int i=N;i<len;i++) 29 { 30 sum-=(c[s[i-N]]-1)*tmp; 31 sum*=NC; 32 sum+=c[s[i]]-1; 33 if(!Hash[sum]) {ans++;Hash[sum]=1;} 34 } 35 printf("%d\n",ans); 36 return 0; 37 }
CF 584 C Marina and Vasya
补题。分类讨论。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn=1e5+10; 7 char a[maxn],b[maxn],c[maxn]; 8 9 char no(char a) 10 { 11 for(char i='a';i<='z';i++) 12 if(i!=a) return i; 13 } 14 15 char no(char a,char b) 16 { 17 for(char i='a';i<='z';i++) 18 if(i!=a&&i!=b) return i; 19 } 20 21 int main(void) 22 { 23 int n,t; 24 scanf("%d%d",&n,&t); 25 scanf("%s%s",a,b); 26 int len=strlen(a),same=0; 27 for(int i=0;i<len;i++) same+=(a[i]==b[i]); 28 int dif=len-same,ok; 29 if((dif+1)/2>t) ok=0; 30 else 31 { 32 ok=1; 33 int p=max(0,t-dif),q=dif-min(t,dif),r=min(t,dif)-q; 34 for(int i=0;i<len;i++) 35 { 36 if(a[i]==b[i]) 37 { 38 if(p) {c[i]=no(a[i]);p--;} 39 else c[i]=a[i]; 40 } 41 else 42 { 43 if(r){r--; c[i]=no(a[i],b[i]);} 44 else if(q) {q--; c[i]=a[i];} 45 else c[i]=b[i]; 46 } 47 } 48 } 49 if(ok) for(int i=0;i<len;i++) putchar(c[i]); 50 else printf("-1"); 51 puts(""); 52 return 0; 53 }
10.7
UESTC 88 Fold The Paper
暴搜20那边。500那边dp。
状态dp[i][cur]表示前i个中取的最后一个为奇(cur=1)或偶(cur=0)的最大值。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int INF=2e8; 7 int sum[510],dp[510][2]; 8 int num[21][510]; 9 int choose[21]; 10 int N,M; 11 12 bool judge(int x) 13 { 14 int last=0; 15 for(int i=1;i<=N;i++) 16 { 17 if(x&(1<<(i-1))) 18 { 19 choose[i]=1; 20 if(last&&!((i-last)&1)) return false; 21 last=i; 22 } 23 else choose[i]=0; 24 } 25 return true; 26 } 27 28 void getsum(void) 29 { 30 memset(sum,0,sizeof(sum)); 31 for(int i=1;i<=N;i++) if(choose[i]) 32 for(int j=1;j<=M;j++) 33 sum[j]+=num[i][j]; 34 return; 35 } 36 37 int main(void) 38 { 39 dp[0][0]=dp[0][1]=-INF; 40 int T ; cin>>T; 41 for(int kase=1;kase<=T;kase++) 42 { 43 scanf("%d%d",&N,&M); 44 for(int i=1;i<=N;i++) 45 for(int j=1;j<=M;j++) 46 scanf("%d",&num[i][j]); 47 int ans=-INF; 48 for(int i=1;i<(1<<N);i++) 49 { 50 if(!judge(i)) continue; 51 getsum(); 52 for(int j=1;j<=M;j++) 53 { 54 int cur=j&1; 55 dp[j][cur]=max(sum[j],max(dp[j-1][cur^1]+sum[j],dp[j-1][cur])); 56 dp[j][cur^1]=dp[j-1][cur^1]; 57 } 58 ans=max(ans,max(dp[M][0],dp[M][1])); 59 } 60 printf("Case #%d: %d\n",kase,ans); 61 } 62 return 0; 63 }
CF 584 D Dima and Lisa
暴力。有两个知识点。
1.哥德巴赫猜想。
2.1e9内相邻的素数差<300。
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 bool is_prime(int x) 6 { 7 if(x<=1) return false; 8 for(int i=2;i*i<=x;i++) 9 if(x%i==0) return false; 10 return true; 11 } 12 13 int main(void) 14 { 15 int a,b,c=0; 16 scanf("%d",&a); 17 if(is_prime(a)) printf("1\n%d\n",a); 18 else 19 { 20 b=a-2; 21 while(!is_prime(b)) b--; 22 a-=b; 23 if(is_prime(a)) printf("2\n%d %d\n",a,b); 24 else 25 { 26 while(!is_prime(a)||!is_prime(c)) c++,a--; 27 printf("3\n%d %d %d\n",a,b,c); 28 } 29 } 30 return 0; 31 }
CF 584 E Anton and Ira
最小cost就是每个字符在两个串中的距离差之和。
移动时只要保证每个字符都不做多余的移动即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <vector> 5 using namespace std; 6 typedef pair<int,int> pii; 7 const int maxn=3000; 8 int p[maxn],s[maxn]; 9 int pp[maxn],ps[maxn]; 10 vector<pii> ans; 11 12 int main(void) 13 { 14 int n; scanf("%d\n",&n); 15 for(int i=1;i<=n;i++) 16 { 17 scanf("%d",p+i); 18 pp[p[i]]=i; 19 } 20 for(int i=1;i<=n;i++) 21 { 22 scanf("%d",s+i); 23 ps[s[i]]=i; 24 } 25 int cost=0; 26 for(int i=1;i<=n;i++) while(p[i]!=s[i]) 27 { 28 int x=s[i],px=pp[x],py=px-1,y=p[py]; 29 while(ps[y]<px) {py--;y=p[py];} 30 swap(p[px],p[py]); 31 swap(pp[x],pp[y]); 32 ans.push_back(pii(px,py)); 33 cost+=px-py; 34 } 35 printf("%d\n%d\n",cost,ans.size()); 36 for(int i=0;i<ans.size();i++) printf("%d %d\n",ans[i].first,ans[i].second); 37 return 0; 38 }
10.9
秘制蛙。
10.10
UESCT 86 Divide
原理上是简单贪心。处理上有技巧。
先把所有物品保存在sum[]里。再处理进位。
处理进位的时候在carry[]里标记某一位能否由比它小的物品组合凑成。
再从最高位往后扫一遍。
如果一个物品是偶数件。它必然能等分。
如果一个物品能被比它小的物品凑成。
i)如果它是奇数个。加上凑成的一件正好等分。
ii)如果它是偶数个。凑成的那一件必然能拆成两个半个(因为所有都是2^ai大小)。也能等分。
所以扫到第一个个数为奇数且不能由比它小的物品凑成的物品时。就能计算答案了。
答案就是这件物品减去所有比它小的物品。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 const int maxn=111111; 8 int carry[maxn]; 9 LL sum[maxn]; 10 11 int main(void) 12 { 13 int T; cin>>T; 14 for(int kase=1;kase<=T;kase++) 15 { 16 int N; scanf("%d",&N); 17 int st=0; 18 memset(sum,0,sizeof(sum)); 19 for(int i=0;i<N;i++) 20 { 21 int a,x; 22 scanf("%d%d",&a,&x); 23 sum[a]+=(LL)x; 24 st=max(st,a); 25 } 26 memset(carry,0,sizeof(carry)); 27 for(int i=0;i<=st;i++) 28 { 29 if(sum[i]/2) carry[i+1]=1; 30 sum[i+1]+=sum[i]/2; 31 sum[i]%=2; 32 } 33 while(st&&(!sum[st]||carry[st])) st--; 34 printf("Case #%d: ",kase); 35 if(!st) printf("%d",sum[st]); 36 else 37 { 38 for(int i=0;i<=st;i++) 39 { 40 if(sum[i]>1) {sum[i]-=2;sum[i+1]++;} 41 if(sum[i]) sum[i+1]++; 42 } 43 while(st&&!sum[st]) st--; 44 for(int i=st;i>=0;i--) printf("%d",sum[i]); 45 } 46 puts(""); 47 } 48 return 0; 49 }
补BC。
HDU 5501 The Highest Mark
背包好想。贪心的部分赛时没想到。Hack时看别人代码也没想明白QAQ。
其实考虑物品选定后如何排序就好了。题解很清楚了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 int dp[3010]; 7 8 struct node 9 { 10 int A,B,C; 11 }p[1010]; 12 13 bool cmp(node a,node b) 14 { 15 return a.C*b.B<b.C*a.B; 16 } 17 18 int main(void) 19 { 20 int T; cin>>T; 21 while(T--) 22 { 23 int n,t; 24 scanf("%d%d",&n,&t); 25 for(int i=0;i<n;i++) scanf("%d%d%d",&p[i].A,&p[i].B,&p[i].C); 26 sort(p,p+n,cmp); 27 memset(dp,0,sizeof(dp)); 28 for(int i=0;i<n;i++) 29 for(int V=t;V>=p[i].C;V--) 30 dp[V]=max(dp[V],dp[V-p[i].C]+p[i].A-V*p[i].B); 31 int ans=0; 32 for(int i=0;i<=t;i++) ans=max(ans,dp[i]); 33 printf("%d\n",ans); 34 } 35 return 0; 36 }