https://vjudge.net/problem/UVA-12520
题意:n*n网格中染色m个格子,染色格子的最长轮廓线
贪心
将格子分为4类
1、隔一个选一个,互不相邻的格子
2、4个角上的格子
3、边界除角的格子
4、内部的格子
4类从上到下依次选
1对答案有4的贡献
2对答案无贡献
3对答案有-2的贡献
4对答案有-4的贡献
对n奇偶分类讨论
当n为奇数时,在分左上角的格子在第1类还是第2类讨论
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
freopen("data.txt","r",stdin);
freopen("my.txt","w",stdout);
long long ans1,ans2,n,sum,rest,now,tmp;
while(scanf("%lld%lld",&n,&sum)!=EOF)
{
if(!n) return 0;
if(n&1)
{
if(sum<=n*n>>1 || sum<=n*n/2+1)
{
printf("%lld\n",sum<<2);
continue;
}
if(sum<=n*n/2+4) ans1=n*n/2*4;
else
{
tmp=sum-4-n*n/2;
ans1=n*n/2<<2;
rest=n/2-1<<2;
if(tmp<=rest) ans1-=tmp<<1;
else
{
ans1-=rest<<1;
tmp-=rest;
ans1-=tmp<<2;
}
}
ans2=n*n/2+1<<2;
now=n*n/2+1;
rest=n/2<<2;
if(sum-now<=rest) ans2-=sum-now<<1;
else
{
ans2-=rest<<1;
now+=rest;
ans2-=sum-now<<2;
}
printf("%lld\n",max(ans1,ans2));
}
else
{
if(sum<=n*n>>1)
{
printf("%lld\n",sum<<2);
continue;
}
if(sum<=n*n/2+2)
{
printf("%lld\n",n*n/2*4);
continue;
}
ans1=n*n>>1<<2;
tmp=sum-n*n/2-2;
rest=n/2-1<<2;
if(tmp<=rest) ans1-=tmp<<1;
else
{
ans1-=rest<<1;
tmp-=rest;
ans1-=tmp<<2;
}
printf("%lld\n",ans1);
}
}
}
同一种思路大佬的写法就是短
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
ll l,n,a,b,c,ans;
ll cal()
{
if(n<=a) return n*4;
if(n<=a+b) return a*4;
if(n<=a+b+c) return a*4-(n-a-b)*2;
return a*4-c*2-(n-a-b-c)*4;
}
int main()
{
freopen("data.txt","r",stdin);
freopen("std.txt","w",stdout);
while(cin>>l>>n,l||n)
{
if(l%2==0)
{
a=l*l/2;
b=2;
c=l/2-1<<2;
ans=cal();
}
else
{
a=l*l/2;
b=l==1 ? 1:4;
c=l==0 ? 0:(l-3)/2*4;
ans=cal();
a=l*l/2+1;
b=0;
c=(l-1)/2*4;
ans=max(ans,cal());
}
cout<<ans<<endl;
}
}
















