全是简单模拟题,没啥好讲的
A.Wall Street Monopoly
区间dp,预处理一个前缀和,然后写一个树状数组查询区间最值就完事了。
#include
#define lowbit(x) x&(-x)
using namespace std;
typedef long long ll;
const int N = 1e2+5;
ll sum[N],Max[N],dp[N][N],y[N];
inline void update(int l){
Max[l] = y[l];
for(int i = 1;i < lowbit(l);i <<= 1) Max[l] = max(Max[l],Max[l-i]);
return ;
}
inline ll query(int l,int r){
ll res = y[r];
while(l <= r){
res = max(res,y[r]);
for(--r;r-l >= lowbit(r);r -= lowbit(r)) res = max(res,Max[r]);
}
return res;
}
void init(int n){
for(int i = 1;i <= n;++i){
for(int j = 1;j <= n;++j)
dp[i][j] = 2e18;
dp[i][i] = 0;
}
return ;
}
int main(){
int n,T,cas = 0;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(Max,0,sizeof(Max));
memset(sum,0,sizeof(sum));
init(n);
for(int i = 1;i <= n;++i){
scanf("%lld%lld",&sum[i],&y[i]);
update(i);
sum[i] += sum[i-1];
}
printf("The minimum cost for lot #%d is ",++cas);
if(n == 1) printf("$0.\n\n");
else{
for(int i = 2;i <= n;++i){
int pre = i-1;
int now = i;
dp[pre][now] = min(sum[pre]-sum[pre-1],y[pre])*min(y[now],sum[now]-sum[now-1]);
}
for(int l = 3;l <= n;++l){
for(int i = 1;i+l-1 <= n;++i){
int j = i+l-1;
for(int k = i;k < j;++k){
ll t1 = min(sum[k]-sum[i-1],query(i,k));
ll t2 = min(sum[j]-sum[k],query(k+1,j));
dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+t1*t2);
}
}
}
printf("$%lld.\n\n",dp[1][n]*100);
}
}
return 0;
}
F.Metallic Equipment Rigid
数学题,判线段是否在圆内或者和圆相交。
#include
using namespace std;
const int N = 1e3+5;
const double INFINV=1e10;
const double ESP=1e-8;
vector<pair<double,double> > V,Y;
typedef pair<double,double> PAIR;
double r[N];
bool vis[N];
vector <int> ans;
bool judge(PAIR P,PAIR yuan,double R)// 判断是否在圆内
{
if( (P.first-yuan.first)*(P.first-yuan.first) + (P.second-yuan.second)*(P.second-yuan.second) -R*R <=0)
return 1;
return 0;
}
bool Judis(PAIR P1,PAIR P2,PAIR yuan,double R){
if(judge(P1,yuan,R)&&judge(P2,yuan,R))//都在圆内 不相交
return true;
if(!judge(P1,yuan,R)&&judge(P2,yuan,R)||judge(P1,yuan,R)&&!judge(P2,yuan,R))//一个圆内一个圆外 相交
return true;
double A,B,C,dist1,dist2,angle1,angle2;//Ax+By+C=0;//(y1-y2)x +(x2-x1)y +x1y2-y1x2=0
if(P1.first==P2.first)
A=1,B=0,C= -P1.first;
else if(P1.second==P2.second)
A=0,B=1,C= -P1.second;
else
{
A = P1.second-P2.second;
B = P2.first-P1.first;
C = P1.first*P2.second - P1.second*P2.first;
}
dist1 = A * yuan.first + B * yuan.second + C;
dist1 *= dist1;
dist2 = (A * A + B * B) * R * R;
if (dist1 > dist2) return false;//点到直线距离大于半径r 不相交
angle1 = (yuan.first - P1.first) * (P2.first - P1.first) + (yuan.second - P1.second) * (P2.second - P1.second);
angle2 = (yuan.first - P2.first) * (P1.first - P2.first) + (yuan.second - P2.second) * (P1.second - P2.second);
if (angle1 > 0 && angle2 > 0) return true;//余弦都为正,则是锐角 相交
return false;//不相交
}
int main()
{
int n,m,T,cas = 0;
double x,y,rr;
scanf("%d",&T);
while(T--){
V.clear();
Y.clear();
ans.clear();
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;++i){
vis[i] = 0;
scanf("%lf%lf%lf",&x,&y,&r[i]);
Y.push_back(make_pair(x,y));
}
for(int i = 1;i <= m;++i){
scanf("%lf%lf",&x,&y);
V.push_back(make_pair(x,y));
}
for(int i = 1;i < V.size();++i){
for(int j = 0;j < Y.size();++j){
if(vis[j+1]) continue;
if(Judis(V[i-1],V[i],Y[j],r[j+1])){
vis[j+1] = 1;
ans.push_back(j+1);
}
}
}
printf("Compound #%d: ",++cas);
if(ans.size()){
sort(ans.begin(),ans.end());
printf("Reptile triggered these cameras:");
for(int i = 0;i < ans.size();++i) printf(" %d",ans[i]);
printf("\n\n");
}
else printf("Rigid Reptile was undetected\n\n");
}
return 0;
}
F.Balanced Strings
dp就完事了,因为所有子串都是和谐的串,所以两种音应该交叉进行,注意第一个字符的处理即可。
#include
using namespace std;
typedef long long ll;
const int N = 1e2+5;
const ll INF = 2e18;
const double eps = 1e-6;
const double Pi = 3.14159265358979;
ll dp[105][3];
map<char,int> mp;
int main() {
int T;
scanf("%d",&T);
string s1 = "aeiouy";
for(int i=0;i<6;i++) mp[s1[i]] = 1;
int ct = 1;
while(T--) {
memset(dp,0,sizeof(dp));
string s;
cin>>s;
printf("String #%d: ",ct++);
if(s[0]=='?') dp[0][1] = 6,dp[0][2] = 20;
else if(mp[s[0]]) dp[0][1] = 1;
else dp[0][2] = 1;
for(int i=1;i<s.length();i++){
if(s[i]!='?'){
if(mp[s[i]]) dp[i][1] = dp[i-1][2];
else dp[i][2] = dp[i-1][1];
}
else dp[i][2] = dp[i-1][1]*20,dp[i][1] = dp[i-1][2]*6;
}
int len = s.length();
printf("%lld\n\n",dp[len-1][1]+dp[len-1][2]);
}
return 0;
}
H.Reach for the Stars
题解是状压。。。现场写了个搜索。。。应该是数据水了。。。
#include
using namespace std;
typedef long long ll;
const int N = 1e2+5;
const ll INF = 2e18;
const double eps = 1e-6;
const double Pi = 3.14159265358979;
char mp[15][15];
int vis[15][15],ans,steps;
struct node{
int x, y;
int p;
node(){}
node(int x,int y,int p):x(x),y(y),p(p){}
bool operator < (node c){
return p < c.p;
}
} s[100];
inline bool check1(int x,int y){
if(mp[x-1][y] != '#' || mp[x+1][y] != '#' || mp[x][y-1] != '#' || mp[x][y+1] != '#') return 0;
return 1;
}
inline bool check2(int x,int y){
if(!vis[x-1][y] || !vis[x+1][y] || !vis[x][y-1] || !vis[x][y+1]) return 1;
return 0;
}
inline bool judge(int n,int m){
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)
if(!vis[i][j] && mp[i][j] == '#') return 0;
return 1;
}
inline void update(const int &i,const int &j,int &rest){
++vis[i][j];
if(vis[i][j] == 1) rest -= 1;
return ;
}
inline void Update(const int &i,const int &j,int &rest) {
update(i,j,rest);
update(i+1,j,rest);
update(i,j+1,rest);
update(i-1,j,rest);
update(i,j-1,rest);
return ;
}
inline void hs(const int &i,const int &j,int &rest) {
--vis[i][j];
if(vis[i][j] == 0) rest += 1;
return ;
}
inline void Hs(const int &i,const int &j,int &rest) {
hs(i,j,rest);
hs(i+1,j,rest);
hs(i,j+1,rest);
hs(i-1,j,rest);
hs(i,j-1,rest);
return ;
}
void dfs(int now,int res,int rest) {
if(rest == 0) {
ans = min(ans,res);
return;
}
if(res+(rest+4)/5 >= ans) return;
int x = s[now].x, y = s[now].y;
if(now == steps){
++res;
Update(x,y,rest);
if(rest == 0) ans = min(ans,res);
Hs(x,y,rest);
--res;
return;
}
if(check2(x,y)){
++res;
Update(x,y,rest);
dfs(now+1,res,rest);
Hs(x,y,rest);
--res;
}
dfs(now+1,res,rest);
return;
}
int main(){
int n,m,T,cas = 0;
scanf("%d",&T);
while(T--){
memset(mp,0,sizeof(mp));
memset(vis,0,sizeof(vis));
int sum = 0;
scanf("%d%d",&n,&m);
printf("Image #%d: ",++cas);
for(int i = 1;i <= n;++i){
scanf("%s",mp[i]+1);
for(int j = 1;j <= m;++j)
if(mp[i][j] == '#') sum++;
}
ans = 0;steps = 0;
for(int i = 2;i < n;++i)
for(int j = 2;j < m;++j)
if(mp[i][j] == '#' && check1(i,j)){
++ans;
vis[i][j] = vis[i - 1][j] = vis[i][j - 1] = vis[i + 1][j] = vis[i][j + 1] = 1;
s[++steps] = node(i,j,min(min(i-1,j-1),min(n-i,m-j)));
}
if(!judge(n,m)) printf("impossible\n\n");
else{
memset(vis, 0, sizeof(vis));
int res = 0;
for(int i = 1;i <= m;++i){
if(mp[1][i] == '#' && vis[1][i] == 0) ++res,Update(2,i,sum);
if(mp[n][i] == '#' && vis[n][i] == 0) ++res,Update(n-1,i,sum);
}
for(int i = 1;i <= n;++i){
if(mp[i][1] == '#' && vis[i][1] == 0) ++res,Update(i,2,sum);
if(mp[i][m] == '#' && vis[i][m] == 0) ++res,Update(i,m-1,sum);
}
sort(s+1,s+1+steps);
dfs(1,res,sum);
printf("%d\n\n", ans);
}
}
return 0;
}
I.Longest Path
竞赛图,哈密顿路径,自行百度即可。
#include
using namespace std;
typedef long long ll;
const int N = 5e2+5;
const int MAXM = 200100;
int mp[N][N];
int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
memset(mp,0,sizeof(mp));
scanf("%d",&n);
for(int i = 0;i < n;++i)
for(int j = 0;j < n;++j)
scanf("%d",&mp[i][j]);
vector<int> v;
v.push_back(0);
for(int i = 1; i < n; i++){
int tmp = v.size()-1;
while(tmp >= 0 && !mp[v[tmp]][i]) tmp--;
v.insert(v.begin()+tmp+1,i);
}
for(int i = 0; i < n; i++) printf("%d%c",v[i]+1,i == n-1 ?'\n' :' ');
}
return 0;
}
J.You Shall Pass
最小割,和小M的作物一样的题目,建个图跑Dinic就完事了
#include
typedef long long ll;
using namespace std;
const int N = 4e4+5;
const int M = 1e6+5;
const int INF = 0x3f3f3f3f;
struct node{
int to,next,flow;
node(){}
node(int to,int next,int flow):to(to),next(next),flow(flow){}
} e[M << 1];
int S,T,tot,head[N],q[N],dep[N],cur[N];
void init(int n){
memset(head,-1,sizeof(head));
tot = -1;
S = 0;
T = n+n*n*2+1;
return ;
}
void add(int u,int v,int w){
e[++tot] = node(v,head[u],w);
head[u] = tot;
e[++tot] = node(u,head[v],0);
head[v] = tot;
return ;
}
inline bool bfs(){
memset(dep,0,sizeof(dep));
int st = 0,ed = 1;
q[st] = S;dep[S] = 1;
while(st != ed){
int u = q[st++];
for(int i = head[u];~i;i = e[i].next){
int v = e[i].to;
if(!dep[v] && e[i].flow > 0){
dep[v] = dep[u]+1;
if(v == T) return 1;
q[ed++] = v;
}
}
}
return dep[T];
}
inline int dfs(int u,int nowflow){
if(u == T || !nowflow) return nowflow;
int totflow = 0;
for(int &i = cur[u];~i;i = e[i].next){
int v = e[i].to;
if(dep[v] == dep[u]+1 && e[i].flow > 0 && nowflow-totflow > 0){
int tflow = dfs(v,min(nowflow-totflow,e[i].flow));
e[i].flow -= tflow;
e[(i^1)].flow += tflow;
totflow += tflow;
nowflow -= tflow;
if(nowflow <= 0) break;
}
}
return totflow;
}
inline int Dinic(){
int ans = 0;
while(bfs()) memcpy(cur,head,sizeof(head)),ans += dfs(S,INF);
return ans;
}
int main(){
int n,TT;
scanf("%d",&TT);
while(TT--){
scanf("%d",&n);
init(n);
double t;
int ans = 0;
for(int i = 1;i <= n;++i){
scanf("%lf",&t);
int tt = round(t*100);
add(S,i,tt);
ans += tt;
}
for(int i = 1;i <= n;++i){
scanf("%lf",&t);
int tt = round(t*100);
add(i,T,tt);
ans += tt;
}
for(int i = 1;i <= n;++i){
for(int j = 1;j <= n;++j){
scanf("%lf",&t);
int tt = round(t*100);
add(n+(i-1)*n+j,i,INF);
add(n+(i-1)*n+j,j,INF);
add(S,n+(i-1)*n+j,tt);
add(i,n+n*n+(i-1)*n+j,INF);
add(j,n+n*n+(i-1)*n+j,INF);
add(n+n*n+(i-1)*n+j,T,tt);
ans += (tt << 1);
}
}
printf("%.2f\n",(double)(ans-Dinic())/100.0);
}
return 0;
}