【SMOJ模擬】2018.12.26 反正都是原題系列2
阿新 • • 發佈:2019-01-05
【前言】
原題是
的,然而懶得找。
T1
【題目】
一個
的二維矩陣,第
行第
列的價值是
,初始起點在第
行第
列的格子,要走
步,最終回到起點,每一步可以走四相鄰的格子。每進入一個格子可以得到該格子的價值,可以重複進入相同格子,而且重複進入可以得到當前格子。求能獲得最大價值。
,且
是偶數
【解題思路】
我們可以
一下答案的組成,那麼一定是沿著一條路徑走,然後反覆橫跳,再沿著路徑走回去。
因為所有路徑最長只有
,於是我們可以暴力迭代前
步,剩下的步數直接計算即可。
【參考程式碼】
#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=105,MX=10000;
int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
int n,m,bx,by,K,now,las;
int a[N][N];
ll ans,f[2][N][N];
int read()
{
int ret=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return ret;
}
void init()
{
now=0;las=1;
n=read();m=read();bx=read();by=read();K=read();
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) a[i][j]=read();
memset(f,0xc0,sizeof(f));f[now][bx][by]=0;
}
void walk()
{
now^=1;las^=1;
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) for(int d=0;d<4;++d)
f[now][i][j]=max(f[now][i][j],f[las][i+dx[d]][j+dy[d]]+a[i][j]);
}
void solve()
{
if(K<=MX)
{
for(int i=1;i<=K;++i) walk();
printf("%lld\n",f[now][bx][by]);
}
else
{
for(int i=1;i<=MX/2;++i) walk();
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) for(int d=0;d<4;++d)
ans=max(ans,f[now][i][j]*2-a[i][j]+(ll)(K-MX)/2*(a[i][j]+a[i+dx[d]][j+dy[d]]));
printf("%lld\n",ans);
}
}
int main()
{
freopen("2738.in","r",stdin);
freopen("2738.out","w",stdout);
init();solve();
return 0;
}
T2
【題目】
有一個
的網格,在
秒內每秒會有一場災難,用
來表示,意為
,將
上的數置零,否則加一。初始每個格子上的數字為
,問
秒後所有數之和。
【解題思路】
我們可以對每一條橫線進行考慮,那麼我們要考慮的就是一個線段與圓交的問題,這個可以通過簡單計算完成。我們現在得到每條斜線上的若干個交點,用一個
來維護計算這條斜線上最終所有數字的和即可。
【參考程式碼】
#include<bits/stdc++.h>
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=105;
int lx,ly,n;
ll ans;
vector<pii>p;
set<int>st;
int read()
{
int ret=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return ret;
}
ll sqr(ll x){return x*x;}
struct data
{
ll x,y,r;
void in(){x=read();y=read();r=read();r=sqr(r);}
}a[N];
ll calc()
{
ll res=0;int las=1;
sort(p.begin(),p.end());st.clear();st.insert(0);
//for(int i=0;i<p.size();++i) printf("%d %d\n",p[i].fi,p[i].se); puts("");
for(int i=0;i<(int)p.size() && las<=ly;++i)
{
if(p[i].fi>las) res+=(p[i].fi-las)*(*st.rbegin()),las=p[i].fi;
if(p[i].se>0) st.insert(p[i].se);
else st.erase(-p[i].se);
}
return res;
}
int main()
{
freopen("2741.in","r",stdin);
freopen("2741.out","w",stdout);
lx=read();ly=read();n=read();ans=(ll)lx*ly*n;
for(int i=1;i<=n;++i) a[i].in();
for(int i=1;i<=lx;++i)
{
p.clear();
for(int j=1;j<=n;++j) if(a[j].r>=sqr(i-a[j].x))
{
ll t=sqrt(a[j].r-sqr(i-a[j].x));
p.pb(mkp(a[j].y-t,j));p.pb(mkp(a[j].y+t+1,-j));
}
p.pb(mkp(ly+1,0));
ans-=calc();
}
printf("%lld\n",ans);
return 0;
}
T3
【題目】
有
個人,每個人可以挑戰人也可以被挑戰,現在已知每個人是否挑戰人和是否被挑戰成功。挑戰是有時間順序的。當一個人被挑戰成功後,接下來所有對他的挑戰都會失敗,同時他將不再會挑戰別人。一個人最多挑戰一次人,求滿足要求的方案數。