世界上没有什么困难能阻挡我前进,除非是调试一个水题调了半个小时……
0/40(60?)/0
3403. 数列变换 (Standard IO)Time Limits: 1000 ms Memory Limits: 524288 KB Detailed Limits
Goto ProblemSet |
这道题在听到一位神仙说出解法前,还以为正解是dp……
解法就是将数组不断右移,然后把跳到尾端的移到下一个即将跳到尾端的数字上去。
eg:1 2 3 4
k=2:1 2 1 4 3
k=3:1 2 1 4 2 3
注意到最后一个区间跳跃的数,它应该预判一下n%k是否等于0,如果整除就不用管(我被坑了好久)。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int N=1e6+10; 5 int n; 6 int b[N*2]; 7 int main(){ 8 scanf("%d",&n); 9 for(int i=1;i<=n;i++){ 10 b[i]=i; 11 } 12 for(int k=2;k<=n;k++){ 13 int tail=n-n%k+k-1,re=b[tail]; 14 for(int i=tail;i>=k-1;i-=k){ 15 b[i]=b[i-k]; 16 } 17 if(n%k!=0) 18 b[n+k-1]=re; 19 } 20 for(int i=n;i<=2*n-1;i++) 21 printf("%d ",b[i]); 22 return 0; 23 }
3404. 卡牌游戏 (Standard IO)Time Limits: 1000 ms Memory Limits: 524288 KB Detailed Limits
Goto ProblemSet |
这道题是贪心。
考虑几种情况:
1.只消耗对方攻击牌:
我们用最大的攻击牌攻击对方最小的攻击牌,然后拿次大的攻击次小的,证明如下:
如果存在一个牌x<对方某一攻击牌y,我方共用牌点为X,对方为Y,则我方得分为X-Y,但是可知x-y<0 所以再攻击也不会得到更多优势,故不去攻击。
2.消耗对方所有牌再造成直接伤害:
如果消耗所有牌的话,应当先攻击防御牌,用等大或者稍大的牌消掉防御牌再去攻击其他的,假设能消耗所有攻击牌,则得分为:sum[x]-def[x]-atk[y](sum是我方牌总分数,def是用在攻击防御牌上的总分数,atk是敌方攻击牌总分数)
以上两种情况取最大即可。
不知道为啥只有80分。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 const ll N=1e5+10; 8 ll n,m,ans,maxans; 9 ll atk[N],dfn[N],ca,cb,vis[N],flag1,flag2; 10 ll x[N]; 11 int main(){ 12 freopen("card17.in","r",stdin); 13 scanf("%lld%lld",&n,&m); 14 char a[10]; 15 ca=cb=0; 16 for(ll i=1,k;i<=n;i++){ 17 cin>>a; 18 scanf("%lld",&k); 19 if(a[0]=='A') atk[++ca]=k; 20 else dfn[++cb]=k; 21 } 22 sort(atk+1,atk+ca+1); 23 sort(dfn+1,dfn+cb+1); 24 for(ll i=1;i<=m;i++) scanf("%lld",&x[i]); 25 sort(x+1,x+m+1); 26 ll ans=0; 27 ll i,j; 28 for(i=1,j=1;i<=ca&&j<=m;){ 29 while((x[j]<atk[i]&&j<=m)||vis[j]) j++; 30 if(j>m) break; 31 ans+=x[j]-atk[i]; 32 vis[j]=1; 33 i++; 34 } 35 if(i>ca) flag1=1; 36 for(i=1,j=1;i<=cb&&j<=m;){ 37 while((x[j]<dfn[i]&&j<=m)||vis[j]) j++; 38 if(j>m) break; 39 vis[j]=1,i++; 40 } 41 if(i>cb) flag2=1; 42 if(flag1&flag2) for(i=1;i<=m;i++) if(!vis[i]) ans+=x[i]; 43 maxans=max(ans,maxans); 44 memset(vis,0,sizeof(vis)); 45 flag1=flag2=ans=0; 46 for(i=1,j=1;i<=cb&&j<=m;){ 47 while((x[j]<dfn[i]&&j<=m)||vis[j]) j++; 48 if(j>m) break; 49 vis[j]=1,i++; 50 } 51 if(i>cb) flag2=1; 52 for(i=1,j=1;i<=ca&&j<=m;){ 53 while((x[j]<atk[i]&&j<=m)||vis[j]) j++; 54 if(j>m) break; 55 ans+=x[j]-atk[i]; 56 vis[j]=1; 57 i++; 58 } 59 if(i>ca) flag1=1; 60 if(flag1&flag2) for(i=1;i<=m;i++) if(!vis[i]) ans+=x[i]; 61 maxans=max(maxans,ans); 62 memset(vis,0,sizeof(vis)); 63 flag1=flag2=ans=0; 64 ll pt[N]; 65 for(ll i=m,j=1;i>=1&&j<=ca;){ 66 if(x[i]>atk[j]) ans+=x[i]-atk[j],vis[i]=1,i--,j++; 67 else break; 68 } 69 ll t=0; 70 for(ll i=1;i<=m;i++) if(vis[i]) t++; 71 if(t==ca) flag1=1; 72 for(i=1,j=1;i<=cb&&j<=m;){ 73 while((x[j]<dfn[i]&&j<=m)||vis[j]) j++; 74 if(j>m) break; 75 vis[j]=1,i++; 76 } 77 if(i>cb) flag2=1; 78 if(flag1&flag2) for(i=1;i<=m;i++) if(!vis[i]) ans+=x[i]; 79 maxans=max(maxans,ans); 80 printf("%lld",maxans); 81 return 0; 82 }
3405. 舞台表演 (Standard IO)Time Limits: 1000 ms Memory Limits: 524288 KB Detailed Limits
Goto ProblemSet |
这题调试要了我老命。
读题目,这道题并不难设状态,设f[k][i][j]表示在第k次转弯后停在(i,j)时走的最长步数,
f[k][i][j]=max(f[k-1][x][y]+step),其中(x,y)表示上次停的位置,枚举这个位置,然后更新方向上的step就可以了。
注意一点,初始状态除了起点以外都为-1。
1 #include<bits/stdc++.h> 2 #pragma GCC optimize(3) 3 using namespace std; 4 const int N=210; 5 const int T=1e5+10; 6 int n,m,xx,yy,k; 7 int a[N][N]; 8 int f[N][N][N],ans; 9 struct Time{ 10 int s,t,d; 11 }r[N]; 12 int main(){ 13 scanf("%d%d%d%d%d",&n,&m,&xx,&yy,&k); 14 char q; 15 for(int i=1;i<=n;i++){ 16 for(int j=1;j<=m;j++){ 17 cin>>q; 18 a[i][j]=(q=='.'?0:1); 19 } 20 } 21 int s,t,d; 22 int maxt=0; 23 for(int i=1;i<=k;i++){ 24 scanf("%d%d%d",&s,&t,&d); 25 r[i]=(Time){s,t,d}; 26 } 27 memset(f,-1,sizeof(f)); 28 f[0][xx][yy]=0; 29 for(int i=1;i<=k;i++){ 30 for(int x=1;x<=n;x++){ 31 for(int y=1;y<=m;y++){ 32 if(f[i-1][x][y]==-1) continue; 33 f[i][x][y]=max(f[i][x][y],f[i-1][x][y]); 34 if(r[i].d==1){ 35 for(int step=1;step<=r[i].t-r[i].s+1;step++){ 36 if(a[x-step][y]||x-step<=0) break; 37 f[i][x-step][y]=max(f[i][x-step][y],f[i-1][x][y]+step); 38 if(f[i][x-step][y]>ans) ans=f[i][x-step][y]; 39 } 40 } 41 else if(r[i].d==2){ 42 for(int step=1;step<=r[i].t-r[i].s+1;step++){ 43 if(a[x+step][y]||x+step>n) break; 44 f[i][x+step][y]=max(f[i][x+step][y],f[i-1][x][y]+step); 45 if(f[i][x+step][y]>ans) ans=f[i][x+step][y]; 46 } 47 } 48 else if(r[i].d==3){ 49 for(int step=1;step<=r[i].t-r[i].s+1;step++){ 50 if(a[x][y-step]||y-step<=0) break; 51 f[i][x][y-step]=max(f[i][x][y-step],f[i-1][x][y]+step); 52 if(f[i][x][y-step]>ans) ans=f[i][x][y-step]; 53 } 54 } 55 else{ 56 for(int step=1;step<=r[i].t-r[i].s+1;step++){ 57 if(a[x][y+step]||y+step>m) break; 58 f[i][x][y+step]=max(f[i][x][y+step],f[i-1][x][y]+step); 59 if(f[i][x][y+step]>ans) ans=f[i][x][y+step]; 60 } 61 } 62 } 63 } 64 } 65 printf("%d",ans); 66 return 0; 67 }
总结:下次要比今天多100分,否则就太菜了。