ACM-ICPC 2017 南宁赛区现场赛 L,I,H题
L题:
题目链接:https://nanti.jisuanke.com/t/A1541
题意:找到最小的n且大于L的数字满足2*m(m+1)=n*(n+1);
思路:打表找规律,我脑子不够用,没找出来;规律是:ans[i]=ans[i-1]*6-ans[i-2]+2;
然后再大数模拟下就可以了;
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<string> #include<queue> #include<cstdlib> using namespace std; typedef long long ll; int a[2005][2005],b[2005]; char c[2000]; int main() { b[0]=1; b[1]=2; a[0][0]=3; a[1][0]=0; a[1][1]=2; for(int i=2; i<=300; i++) { for(int j=0; j<b[i-1]; j++) a[i][j]=a[i-1][j]*6; a[i][0]+=2; for(int j=0; j<b[i-2]; j++) a[i][j]-=a[i-2][j]; int v=0; for(int j=0; j<b[i-1]; j++) { if(v==1) { if(a[i][j]<=0) a[i][j]+=9; else { a[i][j]--; v=0; } } else { if(a[i][j]<0) { a[i][j]+=10; v=1; } } } for(int j=0; j<b[i-1]; j++) { a[i][j+1]=a[i][j+1]+a[i][j]/10; a[i][j]=a[i][j]%10; } if(a[i][b[i-1]]>0) b[i]=b[i-1]+1; else b[i]=b[i-1]; } int t; scanf("%d",&t); while(t--) { scanf("%s",c); int n=strlen(c); int k=lower_bound(b,b+300,n)-b; for(int i=k; i<=300; i++) { if(b[i]>n) { for(int j=b[i]-1; j>=0; j--) printf("%d",a[i][j]); printf("\n"); break; } int v=1; for(int j=n-1; j>=0; j--) { if(a[i][j]>c[n-j-1]-'0') break; else if(a[i][j]<c[n-j-1]-'0') { v=0; break; } } if(v==1) { for(int j=b[i]-1; j>=0; j--) printf("%d",a[i][j]); printf("\n"); break; } } } return 0; }
I题:
题目链接:https://nanti.jisuanke.com/t/A1538
题意:有4*4的矩阵,两个人玩游戏,先手从其中任选2*2的矩阵,然后将所选矩阵逆时针转一下,后手从其中任选2*2的矩阵,然后将所选矩阵逆时针转一下,每一轮先手的任 务是让两人的和最大,后手的任务是让两人的和最小,进行k轮,问k轮两人所选的矩阵的所有加和是多少。
思路:k不是很大,而且后面的选择不会影响到前面的选择,所以可以dfs回溯求值
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<cstdlib>
using namespace std;
typedef long long ll;
int inf=99999999;
int a[5][5];
int n;
void L(int x,int y)
{
int p=a[x][y];
a[x][y]=a[x][y+1];
a[x][y+1]=a[x+1][y+1];
a[x+1][y+1]=a[x+1][y];
a[x+1][y]=p;
}
void R(int x,int y)
{
int p=a[x][y];
a[x][y]=a[x+1][y];
a[x+1][y]=a[x+1][y+1];
a[x+1][y+1]=a[x][y+1];
a[x][y+1]=p;
}
int fun(int x,int y)
{
return a[x][y]+a[x][y+1]+a[x+1][y]+a[x+1][y+1];
}
int dfs(int x)
{
if(x==2*n)
{
int mi=inf;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
mi=min(mi,fun(i,j));
return mi;
}
if(x%2==1)
{
int ma=0;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
{
L(i,j);
int ans=fun(i,j)+dfs(x+1);
R(i,j);
ma=max(ma,ans);
}
return ma;
}
int mi=inf;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
{
L(i,j);
int ans=fun(i,j)+dfs(x+1);
R(i,j);
mi=min(mi,ans);
}
return mi;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
scanf("%d",&a[i][j]);
printf("%d\n",dfs(1));
}
}
H题:
题目链接:https://nanti.jisuanke.com/t/A1537
题意:给出n*m的字符型矩阵,'.'表示不存在细胞,’#‘表示存在。若当前活着的细胞旁边(8联通)存在的活着的细胞数小于2,则当前细胞死亡;
若当前活着的细胞旁边存在的活着的细胞数等于2,则当前细胞能够进行到下一次的分裂;
若当前细胞(死细胞或活细胞)旁边存在的活着的细胞数等于3,则当前位置的细胞变活;
若当前的细胞旁边存在的活着的细胞数大于3,则当前细胞死亡;
思路:暴力模拟就可以了,每次更新活细胞在哪个范围里,然后暴力就可以了;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<cstdlib>
using namespace std;
typedef long long ll;
char cc[10];
int a[800][800],b[800][800];
int fun(int x,int y)
{
int s=0;
for(int i=x-1;i<=x+1;i++)
for(int j=y-1;j<=y+1;j++)
{
if(i==x&&j==y)
continue;
if(a[i][j]==1)
s++;
}
return s;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
int n,m;
scanf("%d %d",&n,&m);
int l=400,r=400+n;
int ll=400,rr=400+m;
int l1=l,r1=r;
int ll1=ll,rr1=rr;
int ma=0,p=0;
for(int i=0;i<n;i++)
{
scanf("%s",cc);
for(int j=0;j<m;j++)
{
if(cc[j]=='#')
{
a[i+400][j+400]=1;
b[i+400][j+400]=1;
ma++;
}
}
}
for(int k=1;k<=321;k++)
{
int sum=0;
for(int i=l-1;i<=r+1;i++)
for(int j=ll-1;j<=rr+1;j++)
{
int x=fun(i,j);
if(x<2||x>3)
b[i][j]=0;
else if(x==3)
b[i][j]=1;
if(b[i][j]==1)
{
sum++;
l1=min(l1,i);
r1=max(r1,i);
ll1=min(ll1,j);
rr1=max(rr1,j);
}
}
if(sum>ma)
{
ma=sum;
p=k;
}
if(k==321)
printf("%d %d %d\n",p,ma,sum);
for(int i=l-1;i<=r+1;i++)
for(int j=ll-1;j<=rr+1;j++)
a[i][j]=b[i][j];
l=l1;
r=r1;
ll=ll1;
rr=rr1;
}
}
return 0;
}
浙公网安备 33010602011771号