「JoyOI」P1001 – 1099题解(44 / 99)by hzwer
只写简要题解,详见JoyOI官方题解
我会尽量给出简单直白的代码
「JoyOI1001」第K极值
排序,计算出m并判断其是不是质数
只需要循环到√m即可
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #include<cmath> #include<cstdio> #include<algorithm> using namespace std; int n,k,m; int a[10005]; bool isprime(int x) {     if(x<=1)return false;     for(int i=2;i<=sqrt(x);i++)         if(x%i==0)return false;     return true; } int main() {     scanf("%d%d",&n,&k);     for(int i=1;i<=n;i++)scanf("%d",&a[i]);     sort(a+1,a+n+1);     m=a[n-k+1]-a[k];     if(isprime(m))puts("YES");     else puts("NO");     printf("%d\n",m);     return 0; } | 
「JoyOI1002」NOIP2005谁拿了最多奖学金
模拟
| 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 | #include<cmath> #include<cstdio> #include<algorithm> using namespace std; int n; char ch[105][20],cadre[2],west[2]; int score1,score2,art,tot; int ans,mx; int main() {     scanf("%d",&n);     for(int i=1;i<=n;i++)     {         scanf("%s",ch[i]);         scanf("%d%d%s%s%d",&score1,&score2,cadre,west,&art);         int Money=0;         if(score1>80&&art>=1)Money+=8000;         if(score1>85&&score2>80)Money+=4000;         if(score1>90)Money+=2000;         if(score1>85&&west[0]=='Y')Money+=1000;         if(score2>80&&cadre[0]=='Y')Money+=850;         tot+=Money;         if(Money>mx)             mx=Money,ans=i;     }     printf("%s\n",ch[ans]);     printf("%d\n%d\n",mx,tot);     return 0; } | 
「JoyOI1003」越野跑
如果是平地,来回要花2F时间,否则花U+D的时间
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include<cmath> #include<cstdio> #include<algorithm> using namespace std; int m,t,u,f,d; char ch[2]; int main() {     scanf("%d%d%d%d%d",&m,&t,&u,&f,&d);     for(int i=1;i<=t;i++)     {         scanf("%s",ch);         if(ch[0]=='f')             m-=2*f;         else m-=(u+d);         if(m<0)         {             printf("%d\n",i-1);             return 0;         }     }     return 0; } | 
「JoyOI1004」滑雪
记忆化搜索,从每个点向更低点记忆化深搜
| 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 31 32 33 34 35 | #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int r,c,ans; int h[105][105],f[105][105]; int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; int dfs(int x,int y) {     if(x<1||y<1||x>r||y>c)return 0;     if(f[x][y]!=-1)return f[x][y];     f[x][y]=1;     for(int i=0;i<4;i++)     {         int tx=x+xx[i],ty=y+yy[i];         if(h[tx][ty]<h[x][y])             f[x][y]=max(f[x][y],dfs(tx,ty)+1);     }     return f[x][y]; } int main() {     memset(f,-1,sizeof(f));     scanf("%d%d",&r,&c);     for(int i=1;i<=r;i++)         for(int j=1;j<=c;j++)             scanf("%d",&h[i][j]);     for(int i=1;i<=r;i++)         for(int j=1;j<=c;j++)             if(f[i][j]==-1)                 ans=max(ans,dfs(i,j));     printf("%d\n",ans);     return 0; } | 
「JoyOI1005」NOIP2005采药
01背包,f(i)表示花费i的时间能获得的最大价值
第二重时间倒序循环,保证一种草药只选一次
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int T,n,ans; int f[1005],t[105],w[105]; int main() {     scanf("%d%d",&T,&n);     for(int i=1;i<=n;i++)         scanf("%d%d",&t[i],&w[i]);     for(int i=1;i<=n;i++)         for(int j=T;j>=0;j--)             if(j+t[i]<=T)                 f[j+t[i]]=max(f[j+t[i]],f[j]+w[i]);     for(int i=0;i<=T;i++)         ans=max(ans,f[i]);     printf("%d\n",ans);     return 0; } | 
「JoyOI1006」NOIP2008ISBN号码
模拟
| 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 | #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; char ch[15],ans; int num,cnt; int main() {     scanf("%s",ch+1);     for(int i=1;i<=11;i++)         if(ch[i]!='-')         {             cnt++;             num+=(ch[i]-'0')*cnt;             num%=11;         }     if(num<10)ans=num+'0';     else ans='X';     if(ans==ch[13])puts("Right");     else     {         ch[13]=ans;         printf("%s",ch+1);     }     return 0; } | 
「JoyOI1007」NOIP2008排座椅
先统计划分某一行/列能减少多少说话的对数
贪心取最大的若干行/列
| 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include<cmath> #include<cstdio> #include<vector> #include<algorithm> using namespace std; int m,n,K,L,D; struct data{     int pos,v;     friend bool operator<(data a,data b){         if(a.v==b.v)return a.pos<b.pos;                 return a.v>b.v;     } }r[1005],c[1005]; vector<int>ans1,ans2; int main() {     scanf("%d%d%d%d%d",&m,&n,&K,&L,&D);     for(int i=1;i<=m;i++)         r[i].pos=i;     for(int i=1;i<=n;i++)         c[i].pos=i;     for(int i=1;i<=D;i++)     {         int x,y,p,q;         scanf("%d%d%d%d",&x,&y,&p,&q);         if(x==p)c[min(q,y)].v++;         else r[min(x,p)].v++;     }     sort(r+1,r+m+1);     sort(c+1,c+n+1);     for(int i=1;i<=K;i++)         ans1.push_back(r[i].pos);     for(int i=1;i<=L;i++)         ans2.push_back(c[i].pos);     sort(ans1.begin(),ans1.end());     sort(ans2.begin(),ans2.end());     for(int i=0;i<ans1.size();i++)         printf("%d ",ans1[i]);     puts("");     for(int i=0;i<ans2.size();i++)         printf("%d ",ans2[i]);     puts("");     return 0; } | 
「JoyOI1008」NOIP2008传球游戏
用f(i,j)表示前i次传球,传给j的方案数
\[则f(i,j) => f(i+1,j+1)\]
\[f(i,j) => f(i+1,j-1)\]
\[边界f(0,1) =1\]
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<algorithm> using namespace std; int n,m; int f[35][35]; int g(int x) {     if(x<1)return x+n;     if(x>n)return x-n;     return x; } int main() {     scanf("%d%d",&n,&m);     f[0][1]=1;     for(int i=0;i<=m;i++)         for(int j=1;j<=n;j++)         {             f[i+1][g(j+1)]+=f[i][j];             f[i+1][g(j-1)]+=f[i][j];         }     printf("%d\n",f[m][1]);     return 0; } | 
「JoyOI1009」NOIP2008立体图(略)
「JoyOI1010」NOIP2008笨小猴
统计一下字母的出现次数,然后同1001
| 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 31 32 33 34 35 36 37 38 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; int l,m; int cnt[30]; char ch[105]; bool isprime(int x) {     if(x<=1)return false;     for(int i=2;i<=sqrt(x);i++)         if(x%i==0)return false;     return true; } int main() {     scanf("%s",ch+1);     l=strlen(ch+1);     for(int i=1;i<=l;i++)         cnt[ch[i]-'a']++;     sort(cnt,cnt+26);     for(int i=0;i<=25;i++)         if(cnt[i])         {             m=cnt[25]-cnt[i];             break;         }     if(!isprime(m))     {         m=0;         puts("No Answer");     }     else puts("Lucky Word");     printf("%d\n",m);     return 0; } | 
「JoyOI1011」NOIP2008传纸条
可以看成从(1,1)到(m,n)找两条不相交的路径
f(i,j,k)表示传到第i个人,第一条路径在第j行,第二条路径在第k行的最大价值
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; int m,n; int a[55][55]; int f[105][55][55]; int main() {     scanf("%d%d",&m,&n);     for(int i=1;i<=m;i++)         for(int j=1;j<=n;j++)             scanf("%d",&a[i][j]);     f[1][1][1]=0;     for(int i=1;i<=n+m;i++)         for(int j=1;j<=m&&j<=i;j++)             for(int k=1;k<=m&&k<=i;k++)                 if(j!=k||i==n+m)                 {                     f[i][j][k]=max(f[i][j][k],f[i-1][j][k]);                        f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k-1]);                        f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k]);                        f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]);                      f[i][j][k]+=a[j][i-j+1]+a[k][i-k+1];                 }     printf("%d\n",f[n+m][m][m]);     return 0; } | 
「JoyOI1012」NOIP2008火柴棒等式
枚举A,B验证
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; int n,ans; int cnt[10]={6,2,5,5,4,5,6,3,7,6}; int get(int x) {     if(x==0)return 6;     int tot=0;     while(x)     {         tot+=cnt[x%10];         x/=10;     }     return tot; } int main() {     scanf("%d",&n);     n-=4;     for(int i=0;i<=1000;i++)         for(int j=0;j<=1000;j++)             if(get(i)+get(j)+get(i+j)==n)                 ans++;     printf("%d\n",ans);     return 0; } | 
「JoyOI1013」找啊找啊找GF
用\(F(i,j)\)表示消费 i 金钱 j 点 rp 能泡到的最多妹子
做一个01背包
用\(G(i,j)\)表示最小的代价
| 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 31 32 33 34 35 36 37 38 39 40 41 42 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> #define inf 1000000000 using namespace std; int ans,mn; int n,m,r; int rmb[105],rp[105],Time[105]; int f[105][105],g[105][105]; int main() {     memset(g,127,sizeof(g));     scanf("%d",&n);     for(int i=1;i<=n;i++)         scanf("%d%d%d",&rmb[i],&rp[i],&Time[i]);     scanf("%d%d",&m,&r);     g[0][0]=0;     for(int i=0;i<n;i++)         for(int j=m-rmb[i+1];j>=0;j--)             for(int k=r-rp[i+1];k>=0;k--)                 if(g[j][k]<inf)                 {                     int p=j+rmb[i+1],q=k+rp[i+1];                     if(f[j][k]+1>f[p][q])                     {                                            f[p][q]=f[j][k]+1;                         g[p][q]=g[j][k]+Time[i+1];                     }                     if(f[j][k]+1==f[p][q])                         g[p][q]=min(g[p][q],g[j][k]+Time[i+1]);                     if(f[p][q]>ans)                         ans=f[p][q],mn=g[p][q];                     if(f[p][q]==ans)                         mn=min(mn,g[p][q]);                 }     printf("%d\n",mn);     return 0; } | 
「JoyOI1014」乘法游戏
用dp(l,r)表示将 l 到 r 移动到只剩两张卡片的最小分数
枚举区间内最后一张取出来的牌,则
\[dp(l,r) = min\{dp(l,k)+dp(k,r)+a_l*a_k*a_r\}\]
记忆化搜索
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> #define inf 1000000000 using namespace std; int n; int a[105],f[105][105]; int dp(int l,int r) {     if(l+1==r)return 0;     if(f[l][r]<inf)return f[l][r];     for(int k=l+1;k<=r-1;k++)         f[l][r]=min(f[l][r],dp(l,k)+dp(k,r)+a[l]*a[k]*a[r]);     return f[l][r]; } int main() {     memset(f,127,sizeof(f));     scanf("%d",&n);     for(int i=1;i<=n;i++)         scanf("%d",&a[i]);     printf("%d\n",dp(1,n));             return 0;     } | 
「JoyOI1015」公路乘车
\[F_i表示移动i公里的最小代价\]
\[则F_i=min\{f_{i-j}+m_j\}\]
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> #define inf 1000000000 using namespace std; int n; int m[15],f[105]; int main() {     memset(f,127,sizeof(f));     f[0]=0;     for(int i=1;i<=10;i++)         scanf("%d",&m[i]);     scanf("%d",&n);     for(int i=1;i<=10;i++)         for(int j=0;j<=n;j++)             if(f[j]<inf)                 f[j+i]=min(f[j+i],f[j]+m[i]);     printf("%d\n",f[n]);     return 0; } | 
「JoyOI1016」NOIP2001装箱问题
最简单的01背包问题,f(i)表示能否得到 i 的体积
推荐阅读《背包九讲》
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> #define inf 1000000000 using namespace std; int v,n; int a[35]; bool f[20005]; int main() {     scanf("%d%d",&v,&n);     for(int i=1;i<=n;i++)         scanf("%d",&a[i]);     f[0]=1;     for(int i=1;i<=n;i++)         for(int j=v-a[i];j>=0;j--)             if(f[j])f[j+a[i]]=1;     for(int i=v;i>=0;i--)         if(f[i])         {             printf("%d\n",v-i);             break;         }     return 0; } | 
「JoyOI1017」冗余关系
并查集,依次合并集合,输出有多少次合并是无效的
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> #define inf 1000000000 using namespace std; int n,m,ans; int fa[1005]; int find(int x) {     return x==fa[x]?x:fa[x]=find(fa[x]); } int main() {     scanf("%d%d",&n,&m);     for(int i=1;i<=n;i++)         fa[i]=i;     for(int i=1;i<=m;i++)     {         int u,v;         scanf("%d%d",&u,&v);         u=find(u);v=find(v);         if(u==v)ans++;         fa[u]=v;     }     printf("%d\n",ans);     return 0; } | 
「JoyOI1018」阶乘统计
答案可以直接用long long存下来,去掉0之后输出它的最后几位
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,K,m; int a[25]; ll ans=1; int main() {     scanf("%d%d",&n,&K);     for(int i=1;i<=n;i++)         ans*=i;     while(ans%10==0)ans/=10;     while(ans)     {             a[++m]=ans%10;         ans/=10;     }     for(int i=min(m,K);i>=1;i--)         printf("%d",a[i]);     return 0; } | 
「JoyOI1019」配对
将A数列从小到大排序,B数列从大到小排序,依次配对
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,ans; int a[10005],b[10005]; int main() {     scanf("%d",&n);         for(int i=1;i<=n;i++)         scanf("%d",&a[i]);     for(int i=1;i<=n;i++)         scanf("%d",&b[i]);     sort(a+1,a+n+1);     sort(b+1,b+n+1,greater<int>());     for(int i=1;i<=n;i++)         ans+=abs(a[i]-b[i]);     printf("%d\n",ans);     return 0; } | 
「JoyOI1020」寻找质因数
对每个数字分解质因数
| 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 31 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,mx,ans; int get(int x) {     int ans=1;     for(int i=2;i<=sqrt(x);i++)         while(x%i==0)             x/=i,ans=max(ans,i);     ans=max(ans,x);     return ans; } int main() {     scanf("%d",&n);     for(int i=1;i<=n;i++)     {         int x;scanf("%d",&x);         if(get(x)>mx)             mx=get(x),ans=x;     }     printf("%d\n",ans);     return 0; } | 
「JoyOI1021」线段长度
将坐标排序后,计算每一条小线段对答案的贡献
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n; long long a[10005],ans; int main() {     scanf("%d",&n);     for(int i=1;i<=n;i++)         scanf("%d",&a[i]);     sort(a+1,a+n+1);     for(int i=1;i<n;i++)         ans+=(a[i+1]-a[i])*i*(n-i);     printf("%lld",ans*2);     return 0; } | 
「JoyOI1022」进制转换
从低位开始,用n除以该位的进制数,看结果是否为奇数,注意要开longlong
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; ll n; int p,ans[35]; int main() {     scanf("%lld",&n);     for(ll i=1;p<=32;i*=(-2),p++)         if((n/i)&1)         {             ans[p]=1;             n-=i;         }     while(!ans[p]&&p!=0)p--;     for(int i=p;i>=0;i--)         printf("%d",ans[i]);     return 0; } | 
「JoyOI1023」奶牛的锻炼
用f(i,j)表示第i天结束,疲劳值为j的最远跑步距离
则\(f(i,j)=f(i-1,j-1)+D_i\)
\(f(i,0)=max\{f(i-j,j)\}\)
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,m; int d[2005],f[2005][505]; int main() {     scanf("%d%d",&n,&m);     for(int i=1;i<=n;i++)         scanf("%d",&d[i]);     for(int i=1;i<=n;i++)     {         f[i][0]=f[i-1][0];         for(int j=1;j<=m;j++)         {             f[i][j]=f[i-1][j-1]+d[i];             if(j<=i)f[i][0]=max(f[i][0],f[i-j][j]);         }     }     printf("%d\n",f[n][0]);     return 0; } | 
「JoyOI1024」外星人的密码数字
根据第一行的字母表得到每个字母的权值
然后用\(O(n^2)\)的dp来求最长不降子序列
\(f_i\)表示以第i个字母结尾的最长不降子序列
\(f_i=max\{f_j\}+1\)(第j个字母权值不大于第i个字母)
| 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 31 32 33 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int l,ans; int val[26],f[256]; char ch[256]; int main() {     scanf("%s",ch+1);     for(int i=1;i<=26;i++)         val[ch[i]-'a']=i;     while(scanf("%s",ch+1)!=EOF)     {         l=strlen(ch+1);         ans=0;         memset(f,0,sizeof(f));         for(int i=1;i<=l;i++)             for(int j=0;j<i;j++)                 if(val[ch[i]-'a']>=val[ch[j]-'a'])                 {                     f[i]=max(f[j]+1,f[i]);                     ans=max(ans,f[i]);                 }         printf("%d",ans);     }     return 0; } | 
「JoyOI1025」单数?双数?
不明觉厉
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n; int main() {     scanf("%d",&n);     for(int i=1;i<=n;i++)     {         ll x;         scanf("%lld",&x);         if(x&1)puts("odd");         else puts("even");     }     return 0; } | 
「JoyOI1026」犁田机器人
由于地图小指令少,所以模拟即可
每次把要犁的地for一遍,打上标记,最后统计标记数量
复杂度\(O(XYL)\)
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int X,Y,L,ans; bool mark[255][255]; int main() {     scanf("%d%d%d",&X,&Y,&L);     for(int i=1;i<=L;i++)     {         int x_1,y_1,x_2,y_2;         scanf("%d%d%d%d",&x_1,&y_1,&x_2,&y_2);         for(int j=x_1;j<=x_2;j++)             for(int k=y_1;k<=y_2;k++)                 if(!mark[j][k])                 {                     ans++;                     mark[j][k]=1;                 }     }     printf("%d\n",ans);     return 0; } | 
「JoyOI1027」木瓜地
从(1,1)开始搜索,每次走相邻的最大值,走过的格子赋值为-1
| 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 31 32 33 34 35 36 37 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int a[45][45]; int r,c,ans; int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; void dfs(int x,int y) {     ans+=a[x][y];     if(x==r&&y==c)return;     a[x][y]=-1;     int mxx=0,mxy=0;     for(int d=0;d<4;d++)     {         int dx=x+xx[d],dy=y+yy[d];         if(dx<1||dy<1||dx>r||dy>c)continue;         if(a[dx][dy]>a[mxx][mxy])             mxx=dx,mxy=dy;     }     dfs(mxx,mxy); } int main() {     scanf("%d%d",&r,&c);     for(int i=1;i<=r;i++)         for(int j=1;j<=c;j++)             scanf("%d",&a[i][j]);     dfs(1,1);     printf("%d\n",ans);     return 0; } | 
「JoyOI1028」Bessie的体重
同1016
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int H,n; int s[505]; bool f[45005]; int main() {     scanf("%d%d",&H,&n);     for(int i=1;i<=n;i++)         scanf("%d",&s[i]);     f[0]=1;     for(int i=1;i<=n;i++)         for(int j=H;j>=s[i];j--)             if(f[j-s[i]])f[j]=1;     for(int i=H;i>=0;i--)         if(f[i])         {             printf("%d\n",i);             return 0;         }     return 0; } | 
「JoyOI1029」牛棚回声
枚举答案,正反模拟判断
| 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 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; char a[105],b[105]; bool check(char a[],char b[],int l) {     int l2=strlen(b+1);     for(int i=1;i<=l;i++)         if(a[i]!=b[l2-l+i])return 0;     return 1; } int main() {     scanf("%s",a+1);     scanf("%s",b+1);     int l1=strlen(a+1),l2=strlen(b+1);     for(int i=min(l1,l2);i>=1;i--)         if(check(a,b,i)||check(b,a,i))         {             printf("%d\n",i);             return 0;         }     return 0; } | 
「JoyOI1030」乳草的入侵
从起点开始bfs,注意坐标的方向
| 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 31 32 33 34 35 36 37 38 39 40 41 42 | #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,m,Mx,My,ans; int head,tail=1,qx[10005],qy[10005]; int xx[8]={-1,-1,-1,0,0,1,1,1},yy[8]={1,-1,0,1,-1,1,-1,0}; int d[105][105]; char a[105][105]; void bfs() {     qx[0]=Mx;qy[0]=My;     d[Mx][My]=0;     while(head!=tail)     {         int x=qx[head],y=qy[head];head++;         ans=d[x][y];         for(int i=0;i<8;i++)         {             int dx=x+xx[i],dy=y+yy[i];             if(dx<1||dy<1||dx>m||dy>n||a[dx][dy]=='*'||d[dx][dy]!=-1)                 continue;             d[dx][dy]=d[x][y]+1;             qx[tail]=dx;qy[tail]=dy;tail++;         }     } } int main() {     memset(d,-1,sizeof(d));     scanf("%d%d%d%d",&n,&m,&My,&Mx);     for(int i=m;i>0;i--)         scanf("%s",a[i]+1);     bfs();     printf("%d\n",ans);     return 0; } | 
「JoyOI1031」热浪
求Ts到Te的最短路,随便选种算法写都可以
这里给出的是堆优化的dijkstra
| 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define pa pair<int,int> #define inf 1000000000 #define ll long long using namespace std; int T,C,Ts,Te; int dis[2505]; bool vis[2505]; vector<int>e[2505],c[2505]; priority_queue<pa,vector<pa>,greater<pa> >q; void dijkstra() {     memset(dis,127/3,sizeof(dis));     q.push(make_pair(0,Ts));dis[Ts]=0;     while(!q.empty())     {         int now=q.top().second;q.pop();         if(vis[now])continue;vis[now]=1;         for(int i=0;i<e[now].size();i++)             if(dis[now]+c[now][i]<dis[e[now][i]])             {                 dis[e[now][i]]=dis[now]+c[now][i];                 q.push(make_pair(dis[e[now][i]],e[now][i]));             }     } } int main() {     scanf("%d%d%d%d",&T,&C,&Ts,&Te);     for(int i=1;i<=C;i++)     {         int u,v,w;         scanf("%d%d%d",&u,&v,&w);         e[u].push_back(v);         e[v].push_back(u);         c[u].push_back(w);         c[v].push_back(w);     }     dijkstra();     printf("%d\n",dis[Te]);     return 0; } | 
「JoyOI1032」零花钱
小的面值能整除大面值,因此可以想到一个贪心的做法
先用尽量大的面值凑,最后选一个面值最小的,这样可以使浪费尽可能少
| 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,c,ans; struct data{     int v,b;     friend bool operator<(data a,data b){         return a.v<b.v;     } }a[25]; int main() {     scanf("%d%d",&n,&c);     for(int i=1;i<=n;i++)     {         scanf("%d%d",&a[i].v,&a[i].b);         if(a[i].v>=c)             ans+=a[i].b,a[i].b=0;     }     sort(a+1,a+n+1);     while(1)     {         int now=0;         for(int i=n;i;i--)             while(a[i].v+now<c&&a[i].b)                 now+=a[i].v,a[i].b--;         for(int i=1;i<=n;i++)             if(a[i].b)             {                                now+=a[i].v,a[i].b--;                 break;             }         if(now>=c)ans++;         else break;     }     printf("%d\n",ans);     return 0; } | 
「JoyOI1033」悠闲的漫步
给出一棵树,求出1号点出发的最远距离
搜索或者dp皆可
| 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 31 32 33 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int p; int f[1005],c[1005],d1[1005],d2[1005]; int dfs(int x) {     if(f[x]!=-1)return f[x];     f[x]=1;     if(d1[x])f[x]=max(dfs(d1[x])+1,f[x]);     if(d2[x])f[x]=max(dfs(d2[x])+1,f[x]);     return f[x]; } int main() {     memset(f,-1,sizeof(f));     scanf("%d",&p);     for(int i=2;i<=p;i++)     {         int x;         scanf("%d",&x);         scanf("%d%d",&d1[x],&d2[x]);     }     printf("%d\n",dfs(1));     return 0; } | 
「JoyOI1034」尼克的任务
用f(i)表示到第i分钟,最大的休息时间
若i分钟没有工作开始,则更新f(i+1)
否则要做一个工作
当然最短路也可以
| 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 31 32 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,K; int p[10005],t[10005],f[10005]; int main() {     scanf("%d%d",&n,&K);     for(int i=1;i<=K;i++)         scanf("%d%d",&p[i],&t[i]);     for(int i=2;i<=n;i++)f[i]=-inf;     for(int i=1;i<=n;i++)     {         bool flag=0;         for(int j=1;j<=K;j++)             if(p[j]==i)             {                 f[i+t[j]]=max(f[i+t[j]],f[i]);                 flag=1;             }         if(!flag)f[i+1]=max(f[i+1],f[i]+1);     }     printf("%d\n",f[n+1]);     return 0; } | 
「JoyOI1035」棋盘覆盖
二分图匹配经典问题,先把棋盘黑白染色
一色分为X部,另一色分为Y部,每个黑色点向周围连边,匈牙利算法求最大匹配数量
当然网络流也可以
| 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long #define p(x,y) (x-1)*n+y using namespace std; int n,m,ans; int del[10005]; int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; int lk[10005]; bool vis[10005]; vector<int>e[10005]; bool find(int x) {     for(int i=0;i<e[x].size();i++)         if(!vis[e[x][i]])         {             vis[e[x][i]]=1;             if(!lk[e[x][i]]||find(lk[e[x][i]]))             {                 lk[e[x][i]]=x;                 return 1;             }         }     return 0; } void build(int x,int y) {     for(int d=0;d<4;d++)     {         int dx=x+xx[d],dy=y+yy[d];         if(dx<1||dy<1||dx>n||dy>n)continue;         if(!del[p(dx,dy)])             e[p(x,y)].push_back(p(dx,dy));     } } int main() {     scanf("%d%d",&n,&m);     for(int i=1;i<=m;i++)     {         int x,y;         scanf("%d%d",&x,&y);         del[p(x,y)]=1;     }     for(int i=1;i<=n;i++)         for(int j=1;j<=n;j++)             if(!del[p(i,j)]&&((i+j)&1))build(i,j);     for(int i=1;i<=n*n;i++)         if(!del[i])         {             memset(vis,0,sizeof(vis));             if(find(i))ans++;         }     printf("%d\n",ans);     return 0; } | 
「JoyOI1036」统计数字
把所有数字排序,就能很方便地得出每个数字出现次数了
| 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 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,a[200005]; int main() {     scanf("%d",&n);     for(int i=1;i<=n;i++)         scanf("%d",&a[i]);     sort(a+1,a+n+1);     int cnt=0;     for(int i=1;i<=n;i++)     {         cnt++;         if(a[i]!=a[i+1])         {             printf("%d %d\n",a[i],cnt);             cnt=0;         }     }     return 0; } | 
「JoyOI1037」阶乘统计2
高精度乘法,维护非0的最后20位
| 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 31 32 33 34 35 36 37 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,k; struct data{     int begin,l,v[500005];     data(){         v[1]=1;         l=begin=1;     }     friend void operator*(data &a,int b){         for(int i=a.begin;i<=a.begin+20&&i<=a.l;i++)             a.v[i]*=b;         for(int i=a.begin;i<=a.begin+20&&i<=a.l;i++)         {             a.v[i+1]+=a.v[i]/10;                         a.v[i]%=10;             if(a.v[a.l+1])a.l++;                        while(!a.v[a.begin])a.begin++;         }     } }ans; int main() {     scanf("%d%d",&n,&k);     for(int i=1;i<=n;i++)ans*i;     for(int i=ans.begin+k-1;i>=ans.begin;i--)         printf("%d",ans.v[i]);     return 0; } | 
「JoyOI1038」忠诚
线段树入门题,线段树的学习材料应该比较多,这里提供一个模板供参考
| 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int m,n; int val[400005],ls[400005],rs[400005]; void build(int k,int l,int r) {     ls[k]=l;rs[k]=r;     int mid=(l+r)>>1;     if(l==r)     {         scanf("%d",&val[k]);         return;     }     build(k<<1,l,mid);build(k<<1|1,mid+1,r);     val[k]=min(val[k<<1],val[k<<1|1]); } int query(int k,int x,int y) {     int l=ls[k],r=rs[k],mid=(l+r)>>1;     if(l==x&&y==r)return val[k];     int ans=inf;     if(x<=mid)         ans=min(ans,query(k<<1,x,min(mid,y)));     if(y>mid)         ans=min(ans,query(k<<1|1,max(mid+1,x),y));     return ans;                 } int main() {     scanf("%d%d",&m,&n);     build(1,1,m);     for(int i=1;i<=n;i++)     {         int a,b;         scanf("%d%d",&a,&b);         printf("%d ",query(1,a,b));     }     return 0; } | 
「JoyOI1039」忠诚2
又一道线段树入门题
| 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int m,n; int val[400005],ls[400005],rs[400005]; void build(int k,int l,int r) {     ls[k]=l;rs[k]=r;     int mid=(l+r)>>1;     if(l==r)     {         scanf("%d",&val[k]);         return;     }     build(k<<1,l,mid);build(k<<1|1,mid+1,r);     val[k]=min(val[k<<1],val[k<<1|1]); } int query(int k,int x,int y) {     int l=ls[k],r=rs[k],mid=(l+r)>>1;     if(l==x&&y==r)return val[k];     int ans=inf;     if(x<=mid)         ans=min(ans,query(k<<1,x,min(mid,y)));     if(y>mid)         ans=min(ans,query(k<<1|1,max(mid+1,x),y));     return ans;                 } void modify(int k,int x,int y) {     int l=ls[k],r=rs[k],mid=(l+r)>>1;     if(l==r)     {         val[k]=y;return;     }     if(x<=mid)modify(k<<1,x,y);     else modify(k<<1|1,x,y);     val[k]=min(val[k<<1],val[k<<1|1]); } int main() {     scanf("%d%d",&m,&n);     build(1,1,m);     for(int i=1;i<=n;i++)     {         int p,a,b;         scanf("%d%d%d",&p,&a,&b);         if(p==1)printf("%d ",query(1,a,b));         else modify(1,a,b);     }     return 0; } | 
「JoyOI1040」表达式计算
要求实现高精度加法的表达式计算
倒着扫一遍字符串,遇到数字就把它加到当前数字的最高位
遇到加号就把当前数字加入答案后清空
| 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n; char ch[1505]; struct data{     int l,v[1505];     void clear(){         l=0;         memset(v,0,sizeof(v));     }     data friend operator+(data a,data b){         data c;c.clear();         c.l=max(a.l,b.l);         for(int i=1;i<=c.l;i++)             c.v[i]=a.v[i]+b.v[i];             for(int i=1;i<=c.l;i++)         {             c.v[i+1]+=c.v[i]/10;             c.v[i]%=10;             if(c.v[c.l+1])c.l++;         }         return c;     } }ans,tmp; int main() {     scanf("%s",ch+1);     n=strlen(ch+1);     for(int i=n;i;i--)         if(ch[i]=='+')         {             ans=ans+tmp;             tmp.clear();         }         else tmp.v[++tmp.l]=ch[i]-'0';     ans=ans+tmp;     for(int i=ans.l;i;i--)         printf("%d",ans.v[i]);     return 0; } | 
「JoyOI1041」表达式计算2
要求从左往右计算才不会出现复数
用两个栈从右往左把操作和数字都记下来
然后倒过来高精度计算
| 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,top; char ch[305]; bool opt[305]; struct data{     int l,v[1505];     void clear(){         l=0;         memset(v,0,sizeof(v));     }     data friend operator+(data a,data b){         data c;c.clear();         c.l=max(a.l,b.l);         for(int i=1;i<=c.l;i++)             c.v[i]=a.v[i]+b.v[i];             for(int i=1;i<=c.l;i++)         {             c.v[i+1]+=c.v[i]/10;             c.v[i]%=10;             if(c.v[c.l+1])c.l++;         }         return c;     }     data friend operator-(data a,data b){         data c;c.clear();         c.l=a.l;         for(int i=1;i<=c.l;i++)             if(a.v[i]>=b.v[i])                 c.v[i]=a.v[i]-b.v[i];             else c.v[i]=a.v[i]+10-b.v[i],a.v[i+1]--;         while(c.l&&!c.v[c.l])c.l--;         return c;     } }ans,tmp[305]; int main() {     scanf("%s",ch+1);     n=strlen(ch+1);     top=1;     for(int i=n;i;i--)         if(ch[i]=='+')opt[top]=0,top++;         else if(ch[i]=='-')opt[top]=1,top++;         else tmp[top].v[++tmp[top].l]=ch[i]-'0';     ans=tmp[top];     for(int i=top-1;i;i--)         if(opt[i])ans=ans-tmp[i];         else ans=ans+tmp[i];             for(int i=ans.l;i;i--)         printf("%d",ans.v[i]);     return 0; } | 
「JoyOI1042」表达式计算3
先预处理把乘方变成乘法,然后从左到右计算
用一个临时的变量tmp来处理运算的优先级,即把一连串的乘除一起算完,再考虑加入答案
遇到一个加减符号就把tmp记入答案,tmp重新赋值
否则用tmp进行运算
| 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n,top=1,top2=1; char ch[105]; int opt[105],num[105]; int opt2[105],num2[105]; int main() {     scanf("%s",ch+1);     n=strlen(ch+1);     for(int i=1;i<=n;i++)         if(ch[i]>='0'&&ch[i]<='9')num[top]=num[top]*10+ch[i]-'0';         else          {             top++;             if(ch[i]=='+')opt[top]=1;             if(ch[i]=='-')opt[top]=2;             if(ch[i]=='*')opt[top]=3;             if(ch[i]=='/')opt[top]=4;             if(ch[i]=='^')opt[top]=5;         }     for(int i=2;i<=top;i++)         if(opt[i]==5)             for(int j=1;j<num[i];j++)             {                 opt2[++top2]=3;                 num2[top2]=num[i-1];             }         else             opt2[++top2]=opt[i],num2[top2]=num[i];     int tmp=num[1],ans=0;     for(int i=2;i<=top2;i++)     {         if(opt2[i]==1)ans+=tmp,tmp=num2[i];         if(opt2[i]==2)ans+=tmp,tmp=-num2[i];         if(opt2[i]==3)tmp*=num2[i];         if(opt2[i]==4)tmp/=num2[i];     }     printf("%d\n",ans+tmp);     return 0; } | 
「JoyOI1043」表达式计算4
正经的表达式计算
用一个数字栈+操作栈来实现
从左往右,将扫到的数字入数字栈,将扫到的操作与操作栈的栈顶对比优先级
如果当前操作优先级高,将其入栈
否则从数字栈中取出两个数字,用栈顶的操作进行运算
优先级次序是右括号和栈内左括号,加减,乘除,乘方,未入栈的左括号
| 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #include<cmath> #include<queue> #include<stack> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; stack<ll> num; stack<char> opt; int n,brack; string str; int pri(char opt) {     if(opt=='+'||opt=='-')return 1;     if(opt=='*'||opt=='/')return 2;     if(opt=='^')return 3;     if(opt=='(')return 100;     if(opt=='#')return -inf;     return -100; } ll cal() {     char tmp=opt.top();opt.pop();     ll b=num.top();num.pop();     ll a=num.top();num.pop();     if(tmp=='+')return a+b;     if(tmp=='-')return a-b;     if(tmp=='*')return a*b;     if(tmp=='/')return a/b;     ll ans=1;     for(int i=1;i<=b;i++)         ans*=a;     return ans; } int main() {     cin>>str;n=str.length();     for(int i=0;i<n;i++)         if(str[i]=='(')brack++;         else if(str[i]==')')brack--;     while(brack>0)         brack--,str+=")";     while(brack<0)         brack++,str="("+str;     str=str+'#';opt.push('#');     num.push(0);     int i=0;     while(str[i]!='#'||opt.top()!='#')     {         if(str[i]>='0'&&str[i]<='9')         {             ll tmp=0;             while(str[i]>='0'&&str[i]<='9')                 tmp=tmp*10+str[i]-'0',i++;             num.push(tmp);         }         else         {             if(pri(str[i])>pri(opt.top()))             {                 if(str[i]=='(')str[i]='[';                 opt.push(str[i]),i++;             }             else             {                 if(opt.top()=='[')                     opt.pop(),i++;                 else num.push(cal());             }                              }     }     cout<<num.top()<<endl;     return 0; } | 
「JoyOI1044」数字三角形
ans(i,j)表示走到(i,j)的最大路径和,从上往下一层一层递推
| 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 31 32 33 34 35 | #include<cmath> #include<queue> #include<stack> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int n; int a[1005][1005],ans[1005][1005]; int main() {     scanf("%d",&n);     for(int i=1;i<=n;i++)         for(int j=1;j<=i;j++)         {             scanf("%d",&a[i][j]);             ans[i][j]=-inf;         }     ans[1][1]=a[1][1];     for(int i=1;i<n;i++)         for(int j=1;j<=i;j++)         {             ans[i+1][j]=max(ans[i+1][j],ans[i][j]+a[i+1][j]);             ans[i+1][j+1]=max(ans[i+1][j+1],ans[i][j]+a[i+1][j+1]);         }     int mx=-inf;     for(int i=1;i<=n;i++)         mx=max(mx,ans[n][i]);     printf("%d\n",mx);     return 0; } | 
 
			
黄学长为什么在做TYVJ傻逼题啊
黄学长恐怕是要带新人了,从此化身黄老师
Orz黄老师
Tyvj似乎挂了
现在可以了