1、传教士(bishop)
问题描述:
panzhili王国的疆土恰好是一个矩形,为了管理方便,国王jjs将整个疆土划分成N*M块大小相同的区域。由于jjs希望他的子民也能信教爱教(”打拳”神教),所以他想安排一些传教士到全国各地去传教。但这些传教士的传教形式非常怪异,他们只在自己据点周围特定的区域内传教且领地意识极其强烈(即任意一个传教士的据点都不能在其他传教士的传教区域内,否则就会发生冲突)。现在我们知道传教士的传教区域为以其据点为中心的两条斜对角线上(如图)。现在jjs请你帮忙找出一个合理的安置方案,使得可以在全国范围内安置尽可能多的传教士而又不至于任意两个传教士会发生冲突。
(若A为某传教士的据点,则其传教范围为所有标有X的格子。为不产生冲突,则第二个传教士的据点只能放在上图的空格中。)
输入数据
输入文件共一行,包含两个整数N和M,代表国土的大小,n为水平区域数,m为垂直区域数。
输出数据
输出文件仅一行,包含一个整数,即最多可以安置的传教士的数目。
样例输入bishop.in
3 4
样例输出bishop.out
6
说明:样例安置方案如下图所示,X表示为某传教士的据点。
XXX
OOO
OOO
XXX
对于100%的数据,1<=n,m<=9,且数据规模呈梯度上升。
类似八皇后
对角线一条一条斜着搜索即可
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=12; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,m,ans=0; int vis[50],shift=10; void dfs(int d){ ans=max(ans,d-2); if(d>m+n) return; for(int x=1;x<=d-1;x++){ int y=d-x; if(x<1||x>n||y<1||y>m) continue; //printf("dfs %d %d %d ",d,x,y); if(vis[x-y+shift]) continue; vis[x-y+shift]=1; dfs(d+1); vis[x-y+shift]=0; } } int main(){ freopen("bishop.in","r",stdin); freopen("bishop.out","w",stdout); n=read();m=read(); dfs(2); printf("%d",ans); }
2、czy把妹(czybm)
Czy是个大丧失,非常喜欢bm。他经常挑战bm的极限,同时b很多的mz。(虽然也许质量不容乐观)
这一天,czy又开始了他的极限挑战。在一个数轴上有n个maze,她们都在等待着czy的到来。Czy一开始站在k号妹子的旁边,他需要搞定所有的妹子(由于他向fewdan学会了绝技,所以搞定妹子的时间是无限接近于0的,也就是一瞬间就搞定而不用花额外的时间)。Maze们都很没有耐心,每让她们多等1s,她们就会增加w[i]的不开心值。现在,czy从k号妹子这里出发,以1m/s的速度开始行动,他希望在搞定所有maze的情况下使得她们的不开心值总和最小,于是他找到了即将在NOIP2014 AK的你来帮他解决这个问题。
文件输入:
输入文件的第一行包含一个整数N,2<=N<=1000,表示maze的数量。
第二行包含一个整数V,1<=V<=N,表示开始时czy站在几号maze的旁边.接下来的N行中,每行包含两个用空格隔开的整数D和W,用来描述每个maze,其中0<=D<=1000,0<=W<=1000。D表示MM在数轴上的位置(单位: m),W表示每秒钟会增加的不开心值。
文件输出:
一个整数,最小的不开心值。(答案不超过10^9)
样例输入
4
3
2 2
5 8
6 1
8 7
样例输出
56
对于40%的数据,1<=n<=7
对于100%的数据,1<=n<=1000 0<=D<=1000 0<=w<=1000
想了各种DP和图论模型.......哎
最后搜索加剪枝骗了60分
PS:搜索时注意在那里cnt++和vis[x]=1/0
正解就是区间DP,差一点想出来了,代价计算时有问题
f[i][j][0/1]表示i到j完成,在左或在右
转移考虑从那里走来,以外的都要贡献w*t的代价,预处理前缀和
//搜索 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1005,INF=1e9; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,s,a[N],w[N],vis[N],cnt=0,ans=1e9; void dfs(int x,int t,int val){//printf("dfs %d %d %d ",x,t,val); cnt++;vis[x]=1; if(cnt==n){ans=min(ans,val);return;} int i; for(i=x+1;i<=n;i++) if(!vis[i]) break; if(i<=n){ int tt=t+(a[i]-a[x]); dfs(i,tt,val+tt*w[i]); cnt--;vis[i]=0; } for(i=x-1;i>=1;i--) if(!vis[i]) break;//printf("vis %d hi2 %d %d ",vis[1],x,i); if(i>=1){ int tt=t+(a[x]-a[i]); dfs(i,tt,val+tt*w[i]); cnt--;vis[i]=0; } } int main(){ freopen("czybm.in","r",stdin); freopen("czybm.out","w",stdout); n=read(); s=read(); for(int i=1;i<=n;i++){a[i]=read();w[i]=read();} dfs(s,0,0); printf("%d",ans); }
//区间DP
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=1005; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,st,a[N],w[N],s[N]; int f[N][N][2]; inline int sum(int i,int j){return s[j]-s[i-1];} void dp(){ for(int i=1;i<=n;i++) f[i][i][0]=f[i][i][1]=abs(a[i]-a[st])*s[n]; for(int l=2;l<=n;l++) for(int i=1;i<=n;i++){ int j=i+l-1; if(j>n) break; f[i][j][0]=min(f[i+1][j][0]+(a[i+1]-a[i])*(sum(j+1,n)+sum(1,i)), f[i][j-1][1]+(a[j]-a[j-1])*(sum(j,n)+sum(1,i-1)) +(a[j]-a[i])*(sum(1,i-1)+sum(j+1,n)) ); f[i][j][1]=min(f[i][j-1][1]+(a[j]-a[j-1])*(sum(j,n)+sum(1,i-1)), f[i+1][j][0]+(a[i+1]-a[i])*(sum(1,i)+sum(j+1,n)) +(a[j]-a[i])*(sum(1,i-1)+sum(j+1,n)) ); } } int main(){ //freopen("czybm.in","r",stdin); //freopen("czybm.out","w",stdout); n=read(); st=read(); for(int i=1;i<=n;i++){ a[i]=read();w[i]=read(); s[i]=s[i-1]+w[i];printf("n %d ",i); } dp(); printf("%d",min(f[1][n][0],f[1][n][1])); }