\(\\\)

\(\#A\) 均分纸牌


有\(N\)堆纸牌,每堆有若干张,但纸牌总数必为\(N\)的倍数。可以在任一堆上取若干张纸牌,然后移动给其左右任意一侧的纸牌堆,求将所有的牌堆牌数都变为平均值最少移动次数。

  • \(N\in [0,100]\)
  • 把所有数减掉平均数,自左往右扫描,只要当前数不为\(0\),就将这个数加给右侧的数,累加计数器。
  • 如果加上了一个负数,代表从右侧的堆移动给了左侧,正数则相反。
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 110
#define R register
#define gc getchar
using namespace std; inline int rd(){
int x=0; char c=gc();
while(!isdigit(c)) c=gc();
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x;
} int ave,ans,a[N]; int main(){
int n=rd();
for(R int i=1;i<=n;++i) ave+=(a[i]=rd());
ave/=n;
for(R int i=1;i<=n;++i) a[i]-=ave;
for(R int i=1;i<=n;++i){
ans+=(abs(a[i])>0); a[i+1]+=a[i];
}
printf("%d\n",ans);
return 0;
}

\(\\\)

\(\# B\) 字串变换


给定两个字符串\(A,B\),以及\(N\)个映射\(U_i\rightarrow V_i\),问是否能在十次操作之内通过子串映射的方式将\(A\)改为\(B\)。

  • \(len_A,len_B\in [1,20]\),\(N\in [1,20]\)
  • 为了找到最少次数可以考虑\(BFS\),每次找到一个位置,替换,次数加一加入队列,第一个找到的数为答案。
  • 为了避免重复搜索同一个串,可以使用\(map\)判断,字符串处理上要注意string自带的函数真**强。
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define R register
#define N 30
using namespace std; int tot=1,res;
string a,b,org[N],trs[N];
map<string,int> mp;
queue<pair<string,int> > q; inline string check(string s,int p,int k){
string res="";
if(p+org[k].size()-1>s.size()) return res;
for(R int i=0;i<org[k].size();++i)
if(s[p+i]!=org[k][i])return res;
s.replace(p,org[k].size(),trs[k]);
return s;
} int main(){
cin>>a>>b;
while(cin>>org[tot]>>trs[tot]) ++tot;
q.push(make_pair(a,0));
while(!q.empty()){
int u=q.front().second;
string su=q.front().first; q.pop();
if(!mp[su]) mp[su]=u;
else continue;
if(u>10) break;
if(su==b){res=u;break;}
for(R int i=0;i<su.size();++i)
for(R int j=1;j<=tot;++j){
string sv=check(su,i,j);
if(sv=="") continue;
q.push(make_pair(sv,u+1));
}
}
if(res) printf("%d\n",res);
else puts("NO ANSWER!");
return 0;
}

\(\\\)

\(\#C\) 自由落体


在高为\(H\)的天花板上有\(n\)个小球,体积不计,位置分别为\(0,1,2,…,n-1\)。

在地面上有一个小车(长为\(L\),高为\(K\),距原点距离为\(S_1\))。

已知小球下落距离计算公式为d\(=0.5 \times g \times (t^2)\),其中\(g=10\),\(t\)为下落时间。地面上的小车以速度\(V\)前进。

小车与所有小球同时开始运动,当小球距小车的距离\(\le 0.0001\)时,即认为小球被小车接受(小球落到地面后不能被接受),计算小车能接受到多少个小球。

  • \(1\le H,S_1,V,L,K,n\le 100000\)
  • 解公式,小车在球落地前最远能到达的位置为\(S_2=S_1-V\times \sqrt\frac{2H}{g}\)
  • 最早能接到球且最靠后的位置为\(S_3=S_1-V\times \sqrt\frac{2(H-K)}{g}+L\)
  • 判断区间\([S2,S3]\bigcap[1,n]\)内的整点个数即可,注意精度的限制。
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define R register
using namespace std;
typedef double db; double eps=1e-4; int main(){
db h,s,v,l,k,n;
scanf("%lf%lf%lf%lf%lf%lf",&h,&s,&v,&l,&k,&n);
double t1=sqrt(h/5),t2=sqrt((h-k)/5);
double s1=s-t1*v,s2=s-t2*v+l;
int resl=(int)ceil(max(s1-eps,(double)0)),resr=floor(min(n-1,s2+eps));
printf("%d\n",max(0,resr-resl+1));
return 0;
}

\(\\\)

\(\#D\) 矩形覆盖


给出\(N\)个第一象限的整点,求至多用\(K\)个矩形将其全部覆盖,矩形面积和最小是多少。

矩形可以是点或线,此时面积为\(0\),但所选矩形不可出现面积相交、边相交、顶点相同的情况。

  • \(N\in [1,50]\),\(K\in [1,4]\)

\(DFS:\)

  • 直接钦定每一个点属于哪一个矩形即可,剪枝如下:

    • 每一层判断当前矩形中是否出现不合法情况
    • 当前面积超过已经搜到过的答案
  • 判断有交可以通过分别判断两个维度各自是否有交再去与得到。
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 60
#define R register
#define gc getchar
#define inf 2000000000
using namespace std; int n,k,res=inf,l[5],r[5],u[5],d[5];
struct point{int x,y;}p[N]; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} inline bool check(){
for(R int i=0;i<k;++i)
for(R int j=0;j<i;++j){
bool y=((u[i]>=d[j]&&u[i]<=u[j])||(u[j]>=d[i]&&u[j]<=u[i]));
bool x=((r[i]>=l[j]&&r[i]<=r[j])||(l[i]>=l[j]&&l[i]<=r[j]));
if(x&&y) return 1;
}
return 0;
} void dfs(int x,int sum){
if(check()||sum>=res) return;
if(x>n){res=sum;return;}
for(R int i=0;i<k;++i){
int lsts=(l[i]==inf?0:(r[i]-l[i])*(u[i]-d[i]));
int lstl=l[i],lstr=r[i],lstu=u[i],lstd=d[i];
l[i]=min(l[i],p[x].x); r[i]=max(r[i],p[x].x);
d[i]=min(d[i],p[x].y); u[i]=max(u[i],p[x].y);
dfs(x+1,sum-lsts+(r[i]-l[i])*(u[i]-d[i]));
l[i]=lstl; r[i]=lstr; u[i]=lstu; d[i]=lstd;
}
} int main(){
n=rd(); k=rd();
for(R int i=0;i<k;++i){l[i]=d[i]=inf;r[i]=u[i]=-inf;}
for(R int i=1;i<=n;++i){p[i].x=rd();p[i].y=rd();}
dfs(1,0);
printf("%d\n",res);
return 0;
}

\(DP:\)

  • 本方法已被证明不是完全正确的,但可以通过当年的数据,由于思想可以借鉴所以还是写一写。
  • 首先,按照横坐标为第一关键字,纵坐标为第二关键字排序,设\(f[i][j][k]\)为从第\(i\)个点覆盖到第\(j\)个点用\(k\)个矩形所需的最小面积和。
  • 类区间\(DP\)的思想,枚举断点和两侧的矩形个数,暴力更新。
  • 注意到这样做得到的矩形都是并排的,所以我们需要将坐标系转\(\frac{\pi}{2}\)再做一遍。
  • 当\(4\)个矩形时即可构造数据卡掉这个情况,只需要让横纵向答案都不是并排的即可。
#include<cmath>
#include<cctype>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 60
#define R register
#define gc getchar
#define inf 2000000000
using namespace std; int n,m,f[N][N][5];
struct point{int x,y;}p[N]; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} inline bool cmp(point x,point y){
return (x.x==y.x)?x.y<y.y:x.x<y.x;
} int main(){
n=rd(); m=rd();
for(R int i=0;i<n;++i){p[i].x=rd();p[i].y=rd();}
sort(p,p+n,cmp);
memset(f,0x3f,sizeof(f));
for(R int i=0;i<n;++i)
for(R int j=i+1;j<n;++j){
int l=inf,r=-inf;
for(R int k=i;k<=j;++k){l=min(l,p[k].y);r=max(r,p[k].y);}
f[i][j][1]=(r-l)*(p[j].x-p[i].x);
}
if(m==1){printf("%d\n",f[0][n-1][1]);return 0;}
for(R int i=n-1;i>=0;--i)
for(R int j=i+1;j<n;++j)
for(R int k=2;k<=m;++k)
for(R int p=i+1;p<j;++p)
for(R int t=1;t<k;++t)
if(f[i][j][k])f[i][j][k]=min(f[i][j][k],f[i][p][t]+f[p+1][j][k-t]);
else f[i][j][k]=f[i][p][t]+f[p+1][j][k-t];
int res=f[0][n-1][m];
for(R int i=0;i<n;++i) swap(p[i].x,p[i].y);
sort(p,p+n,cmp);
memset(f,0x3f,sizeof(f));
for(R int i=0;i<n;++i)
for(R int j=i+1;j<n;++j){
int l=inf,r=-inf;
for(R int k=i;k<=j;++k){l=min(l,p[k].y);r=max(r,p[k].y);}
f[i][j][1]=(r-l)*(p[j].x-p[i].x);
}
if(m==1){printf("%d\n",f[0][n-1][1]);return 0;}
for(R int i=n-1;i>=0;--i)
for(R int j=i+1;j<n;++j)
for(R int k=2;k<=m;++k)
for(R int p=i+1;p<j;++p)
for(R int t=1;t<k;++t)
if(f[i][j][k])f[i][j][k]=min(f[i][j][k],f[i][p][t]+f[p+1][j][k-t]);
else f[i][j][k]=f[i][p][t]+f[p+1][j][k-t];
printf("%d\n",min(res,f[0][n-1][m]));
return 0;
}

[ NOIP 2002 ] TG的更多相关文章

  1. NOIP 2002提高组 选数 dfs/暴力

    1008 选数 2002年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 已知 n 个整数 x1,x2,…, ...

  2. NOIP 2002 提高组 字串变换

    题目描述 已知有两个字串 A, B 及一组字串变换的规则(至多6个规则): A1 -> B1 A2 -> B2 规则的含义为:在 A$中的子串 A1 可以变换为 B1.A2 可以变换为 B ...

  3. [ NOIP 2014 ] TG

    \(\\\) \(Day\ 1\) \(\\\) \(\#\ A\) \(Rps\) 定义五种方案的石头剪刀布游戏,两人共进行\(N\)局游戏,已知两人各自的循环节和具体方案,胜者得\(1\)分,败者 ...

  4. NOIP 2002过河卒 Label:dp

    题目描述 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例如 ...

  5. [COGS 0065][NOIP 2002] 字串变换

    65. [NOIP2002] 字串变换 ★★   输入文件:string.in   输出文件:string.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 已知有两个字 ...

  6. 过河卒 NOIp 2002 dp

    题目描述 棋盘上AAA点有一个过河卒,需要走到目标BBB点.卒行走的规则:可以向下.或者向右.同时在棋盘上CCC点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦 ...

  7. [ NOIP 2008 ] TG

    \(\\\) \(\#A\) \(Word\) 给出一个长为\(N\)的小写字母串,判断出现所有字母中最多出现次数减最少出现次数得到的答案是否是质数. \(N\in [1,100]\) 直接按题意开桶 ...

  8. [ NOIP 1998 ] TG

    \(\\\) \(\#A\) 车站 火车从第\(1\)站开出,上车的人数为\(a\),然后到达第\(2\)站,在第\(2\)站有人上.下车,但上.下车的人数相同,因此在第\(2\)站开出时(即在到达第 ...

  9. [ NOIP 2009 ] TG

    \(\\\) \(\#A\) \(Spy\) 给出两个长度均为\(N\)相同的样例串,建立第一个串各个字符向第二个串对应位置字符的映射,并用映射转换给出的长度为\(M\)第三个串,输入保证只有大写字符 ...

随机推荐

  1. Linux 使用pwgen命令创建随机密码

    https://blog.csdn.net/fdipzone/article/details/73864598 http://www.netkou.com/?post=155

  2. [bzoj 1041][HAOI2008]圆周上的整点(枚举)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1041 分析:实质上是求(a,b,c)勾股数的个数,其中c是确定的. 对于勾股数有一组通式: a ...

  3. FreeMarker与Servlet结合示例

    一.最原始示例 1.引入POM依赖 <!-- https://mvnrepository.com/artifact/org.freemarker/freemarker --> <de ...

  4. 条款39: 避免 "向下转换" 继承层次

    基类指针不能调用派生类的独有的成员,即使基类指针指向派生类对象,因为编译器是根据指针的静态类型来确定调用对象在内存中占据的空间的.此时可以使用static_cast来转换,但不要这么做,因为向下转换难 ...

  5. 《Java设计模式》之解释器模式

    解释器模式是类的行为模式.给定一个语言之后,解释器模式能够定义出其文法的一种表示,并同一时候提供一个解释器. client能够使用这个解释器来解释这个语言中的句子. 解释器模式的结构 以下就以一个示意 ...

  6. Sping框架的IOC特性

    IOC(Inversion of Control):控制反转 以下以课程与老师的安排来介绍控制反转. 一个合理的课程编排系统应该围绕培训的内容为核心,而不应该以具体的培训老师为核心,这样才能在正常授课 ...

  7. 【Aladdin Unity3D Shader编程】之二 光照模型(一)

    光照模型 光照模型就是一个公式,使用这个公式来计算在某个点的光照效果. 在标准光照模型里面,我们把进入摄像机的光分为下面四个部分: 自发光 类似生活中的萤火虫等自己能够发光 高光反射 类似生活中的镜子 ...

  8. GammaRay观察Qt程序的运行状况

    GammaRay是KDAB开发的Qt应用程序的软件内省工具.利用QObject内省机制,它允许您在运行时观察和操作应用程序.这既可以在工作站本地使用,也可以在嵌入式目标上远程使用. 通过扩充指令级调试 ...

  9. Android SDK Manager 无法更新问题(转载)

    先看看如何加快更新速度,再说如何更新. 首先更新host文件,如图,打开目录 C:\Windows\System32\drivers\etc,在目录下有hosts文件 打开方式选用“记事本”打开 将一 ...

  10. eclipse.ini启动参数配置的解析及方法

    原文地址 - http://www.uzzf.com/news/18444.html 1.先了解下JVM内存管理机制,JVM内存分为堆内存和非堆内存 2.JVM内存限制 首先JVM内存限制于实际的最大 ...