可能是打智(ka)算(chang)之(da)道(sai)留下的后遗症,看见Rank掉了,想把A掉的题输入优化一下再交一遍,然后就恰了一发罚时,从Rank900掉到了Rank1100…
纯模拟,没什么好说的。
#include
const int inf=0x3f3f3f3f;
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int t,n,m,x,y,tmp,ans;
cin>>t;
while(t--)
{
cin>>n>>m;
ans=inf;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
tmp=m/x*y;
if(m%x)
tmp+=y;
ans=min(ans,tmp);
}
cout<<ans<<endl;
}
}
dfs,取每个分数段里最低的,最终搜索深度为4时,只要用掉的分数不超过输入的分数就行,取一个最大结果输出。
#include
const int inf=0x3f3f3f3f;
using namespace std;
int t,score;
double ans;
void dfs(double s,double g,int c)
{
if(c>4) return;
if(s>score) return;
if(c==4&&s<=score)
{
ans=max(ans,g);
return;
}
dfs(s,g,c+1);
dfs(s+60,g+1,c+1);
dfs(s+62,g+1.7,c+1);
dfs(s+65,g+2,c+1);
dfs(s+67,g+2.3,c+1);
dfs(s+70,g+2.7,c+1);
dfs(s+75,g+3,c+1);
dfs(s+80,g+3.3,c+1);
dfs(s+85,g+3.7,c+1);
dfs(s+90,g+4,c+1);
dfs(s+95,g+4.3,c+1);
}
int main()
{
cin>>t;
while(t--)
{
ans=0;
cin>>score;
dfs(0,0,0);
cout<<fixed<<setprecision(1)<<ans<<endl;
}
}
暴力美学
dp,一开始尝试从(a,b)往(1,1)跑,但是因为有多组测试数据,每组的起点不同导致跑出来的结果在各组数据间不能互通,最后试了一下反着跑,因为起点都是(1,1),所以dp出来的数据可以通用。开局直接从(1,1)跑到(1000,1000),然后打表就完事了。
一开始T了,加了输入优化卡进了时限,900ms还行。
#include
const int inf=0x3f3f3f3f;
using namespace std;
int mem[1010][1010];
int gcd(int a,int b)
{
return b ? gcd(b,a%b) : a;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
for(int i=1;i<=1000;i++)
for(int j=1;j<=1000;j++)
if(gcd(i,j)==1)
mem[i][j]=max(mem[i-1][j],mem[i][j-1])+1;
else
mem[i][j]=max(mem[i-1][j],mem[i][j-1]);
int t,a,b;
cin>>t;
while(t--)
{
cin>>a>>b;
cout<<mem[a][b]<<endl;
}
}
纯模拟,枚举建城市的点,w用来存从(x,y)跑到(i,j)所用的回合数,work存(i,j)城市周围可用工作点的收益,因为城里始终要有一个人工作,所以城市点最优先,其次就是周围的点从大到小。这里加了一个前缀和(代码中变量为k的循环),每次加食物的时候就不用从1开始遍历了。
#include
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int maxn=510;
int t,n,x,y,a[maxn][maxn],w[maxn][maxn],work[maxn][maxn][27],ans;
void solve(int round,int people,int food,int xx,int yy)
{
round++;
food+=work[xx][yy][people];
while(food>=(8*people*people))
people++;
if(people==9)
{
ans=min(ans,round);
return;
}
solve(round,people,food,xx,yy);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>t;
while(t--)
{
ans=inf;
memset(a,0,sizeof(a));
memset(w,0,sizeof(w));
memset(work,0,sizeof(work));
cin>>n>>x>>y;
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
{
cin>>a[i][j];
int dis=abs(x-i)+abs(y-j);
w[i][j]=(dis>>1)+(dis&1?1:0);
}
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
{
int cnt=0;
for(int ii=-3; ii<=3; ++ii)
for(int jj=-3; jj<=3; ++jj)
if((abs(ii)+abs(jj))<=3&&i+ii>=1&&i+ii<=n&&j+jj>=1&&j+jj<=n)
{
work[i][j][++cnt]=a[i+ii][j+jj];
if(ii==0&&jj==0)
swap(work[i][j][cnt],work[i][j][1]);
}
sort(&work[i][j][2],&work[i][j][26],greater<int>());
for(int k=2; k<=9; ++k)
work[i][j][k]+=work[i][j][k-1];
solve(w[i][j],1,0,i,j);
}
cout<<ans<<endl;
}
}
每层的黑块数目单调,无论递增或递减,都是形成一个森林,森林的连通块数量为总点数-总边数。在这题中,相邻的两个圈中,如果有内外黑块边界相接,就形成了一条边,连通块数目就是总黑块数-总边数。每个圈中有一半是黑块,总黑块数=a[1]/2+a[2]/2+…+a[n]/2。对于任意一对相邻的环,设外环有x块,内环有y块,且根据题意x k的大小达到了1e10,O(k)的复杂度会炸,下面是参考的O(√k)算法博客,解释非常详细。 首先,如果蚊子总数少于n* m直接特判输出-1,然后对时间t二分答案,其中对每个t跑一次网络流。直接的思路是源点S连接每个窗户,边容量为各窗户的蚊子数,再从每个窗户向从此窗户出发的t时间内能到达的每个位置连接容量为inf的边,最后从每个窗户到汇点T连接容量为1的边。如果这样建图,在最坏的情况下有nmk+2个点,建图和跑网络流消耗巨大,可以观察到窗户个数k很少,我们可以通过二进制状压,压缩每个格点与所有窗户的连接情况(从第0位开始,若第i位为1,即表示t时间内蚊子可以从第i个窗户到达该点),总状态数只有2^k个,相当于把n *m个点中状态相同的点合并了,且把与汇点连边的容量合并了。#pragma GCC optimize(3)
#include
Matrix
https://www.cnblogs.com/jianjinxiani/p/13361465.html#pragma GCC optimize(3)
#include
Mosquito
#pragma GCC optimize(3)
#include
Function
莫比乌斯反演,我不会。