总目录详见https://blog.csdn.net/mrcrack/article/details/84471041
做题原则,找不到测评地址的题不做。2018-11-28
重走长征路---OI每周刷题记录---6月8日 2015
本周共计 题+题
测评地址:
Codeforces Round #290 (Div. 1)
1.拓扑排序:A.Fox And Names
2.记忆化搜索+map:B. Fox And Jumping
3.dancing link:3074.Sudoku
4.数位dp:3252.Round Numbers
5.模拟:1665.Biker’s Trip Odometer
6.数学:1930.Dead Fraction
7.模拟:1970.The Game
8.状压dp:1185.炮兵阵地 //在线测评地址https://www.luogu.org/problemnew/show/P2704
9.dp:2017: [Usaco2009 Nov]硬币游戏
10.dfs:[Usaco2005 Feb]Rigging the Bovine Election 竞选划区
11.暴力:1661: [Usaco2006 Nov]Big Square 巨大正方形
12.tarjan:1654: [Usaco2006 Jan]The Cow Prom 奶牛舞会
13.dp+矩阵乘法:A:Quad Tiling
14.线段树:B:Garden
15.模拟:D:One-move checkmate
16.二分+贪心:E:ATP
17.费用流:「bzoj3308」九月的咖啡店
Codeforces Round #161 (Div. 2)
18.模拟:A.Beautiful Matrix
19.模拟:B. Squares
20.dfs:C. Circle of Numbers
21.dfs:D.Cycle in Graph
22.模拟:E. Rhombus
2015全国互测 3
23.排列组合:Country
24.「百度之星」数长方形 暴力
25.「百度之星」最强密码 暴力
26.「百度之星」大搬家 dp
题解:
Codeforces Round #290 (Div. 1)
1.拓扑排序:A.Fox And Names
2.记忆化搜索+map:B. Fox And Jumping
3.dancing link:3074.Sudoku
4.数位dp:3252.Round Numbers
5.模拟:1665.Biker’s Trip Odometer
6.数学:1930.Dead Fraction
7.模拟:1970.The Game
8.状压dp:1185.炮兵阵地
//P2704 [NOI2001]炮兵阵地
//在线测评地址https://www.luogu.org/problemnew/show/P2704
//发现,还是可以用状压dp的,先摸索,争取能弄出AC。
//第一步,计算每一行,可能的炮兵放置
//对左移,右移,运算符,还不是太熟,编码后才了解了。
//i<<1左移1位,i<<2左移2位,i>>1右移1位,i>>2右移2位,看到了吗,移动的位数一定放在右边。
//测试了,发现M=10,不考虑山,符合条件的有60个,故,数组在状态处,开到100即可
//if((tmp[j]&b)==0)state[i][cnt[i]]=tmp[j],cnt[i]++,printf("%d tmp%d\n",i,tmp[j]);//此处写成if(tmp[j]&b==0),查了好久,没想到&的优先级这么低
//搜索网络,发现,确实如此。
//写dp时,感觉思路有点乱,还是先停一停,想清楚了,再来。
//在dp的维度上想了很久,跨度一天,还是相通了,感觉很好。
//样例通过,提交20分,测试点2-9WA。2019-3-14
//什么地方有问题,
//以下为20分代码。
//https://www.cnblogs.com/hoskey/p/3737870.html此文转移方程写得不错
//样例通过,提交40分,测试点2,3,5,7-9WA。
//以下为40分代码。2019-3-15
//对比正确代码,跟踪了一个小时,才发现,处理dp时,将数据向下移动2行
//而读取字符串时,却未做同样的处理,导致数据不同步,该错误,难以查出
//牵一发而动全身。2019-3-15
//for(i=2;i<N+2;i++)scanf("%s",map[i]);//此处写成 for(i=0;i<N;i++)scanf("%s",map[i]);
//修改,样例通过,提交AC。2019-3-15
//以下为AC代码。
#include <stdio.h>
#include <string.h>
int N,M,tmp[100],num=0,state[105][100],cnt[100],dp[105][65][65],can[105][100],tmp2[100];//can[i][j]对应i行,j状态,部队数量。dp[i][j] 对应i行,状态j的最多部队数量
char map[105][12];
int max(int a,int b){
return a>b?a:b;
}
void init(){
int i,j,tot,b;
tot=(1<<M)-1;
for(i=0;i<=tot;i++)
if(((i<<1)&i)==0&&((i<<2)&i)==0&&((i>>1)&i)==0&&((i>>2)&i)==0)//先筛出枚举的可能
tmp[num]=i,num++;
for(i=0;i<num;i++){
j=tmp[i];
while(j){
if(j&1)tmp2[i]++;//部队数量
j>>=1;
}
}
state[0][0]=0,can[0][0]=0,cnt[0]=1,state[1][0]=0,can[1][0]=0,cnt[1]=1;//为了方便处理数据,添加2行
for(i=2;i<N+2;i++){
b=0;
for(j=0;j<M;j++)
if(map[i][j]=='H')
b|=(1<<j);
for(j=0;j<num;j++)
if((tmp[j]&b)==0)state[i][cnt[i]]=tmp[j],can[i][cnt[i]]=tmp2[j],cnt[i]++;//此处写成if(tmp[j]&b==0),查了好久,没想到&的优先级这么低
}
}
void solve(){
int i,j,k,p,ans=0;
for(i=2;i<N+2;i++)
for(j=0;j<cnt[i];j++)
for(k=0;k<cnt[i-1];k++)
for(p=0;p<cnt[i-2];p++)
if((state[i][j]&state[i-1][k])==0&&(state[i][j]&state[i-2][p])==0&&(state[i-1][k]&state[i-2][p])==0)
dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][p]+can[i][j]);
for(j=0;j<cnt[N+1];j++)
for(k=0;k<cnt[N];k++)
ans=max(ans,dp[N+1][j][k]);
printf("%d\n",ans);
}
int main(){
int i;
scanf("%d%d",&N,&M);
for(i=2;i<N+2;i++)scanf("%s",map[i]);//此处写成 for(i=0;i<N;i++)scanf("%s",map[i]);
memset(cnt,0,sizeof(cnt)),memset(tmp2,0,sizeof(tmp2)),memset(dp,0,sizeof(dp));
init();
solve();
return 0;
}
//P2704 [NOI2001]炮兵阵地
//在线测评地址https://www.luogu.org/problemnew/show/P2704
//发现,还是可以用状压dp的,先摸索,争取能弄出AC。
//第一步,计算每一行,可能的炮兵放置
//对左移,右移,运算符,还不是太熟,编码后才了解了。
//i<<1左移1位,i<<2左移2位,i>>1右移1位,i>>2右移2位,看到了吗,移动的位数一定放在右边。
//测试了,发现M=10,不考虑山,符合条件的有60个,故,数组在状态处,开到100即可
//if((tmp[j]&b)==0)state[i][cnt[i]]=tmp[j],cnt[i]++,printf("%d tmp%d\n",i,tmp[j]);//此处写成if(tmp[j]&b==0),查了好久,没想到&的优先级这么低
//搜索网络,发现,确实如此。
//写dp时,感觉思路有点乱,还是先停一停,想清楚了,再来。
//在dp的维度上想了很久,跨度一天,还是相通了,感觉很好。
//样例通过,提交20分,测试点2-9WA。2019-3-14
//什么地方有问题,
//以下为20分代码。
//https://www.cnblogs.com/hoskey/p/3737870.html此文转移方程写得不错
//样例通过,提交40分,测试点2,3,5,7-9WA。
//以下为40分代码。2019-3-15
#include <stdio.h>
#include <string.h>
int N,M,tmp[100],num=0,state[105][100],cnt[100],dp[105][65][65],can[105][100],tmp2[100];//can[i][j]对应i行,j状态,部队数量。dp[i][j] 对应i行,状态j的最多部队数量
char map[105][12];
int max(int a,int b){
return a>b?a:b;
}
void init(){
int i,j,tot,b;
tot=(1<<M)-1;
for(i=0;i<=tot;i++)
if(((i<<1)&i)==0&&((i<<2)&i)==0&&((i>>1)&i)==0&&((i>>2)&i)==0)//先筛出枚举的可能
tmp[num]=i,num++;
for(i=0;i<num;i++){
j=tmp[i];
while(j){
if(j&1)tmp2[i]++;//部队数量
j>>=1;
}
}
state[0][0]=0,can[0][0]=0,cnt[0]=1,state[1][0]=0,can[1][0]=0,cnt[1]=1;//为了方便处理数据,添加2行
for(i=2;i<N+2;i++){
b=0;
for(j=0;j<M;j++)
if(map[i][j]=='H')
b|=(1<<j);
for(j=0;j<num;j++)
if((tmp[j]&b)==0)state[i][cnt[i]]=tmp[j],can[i][cnt[i]]=tmp2[j],cnt[i]++;//此处写成if(tmp[j]&b==0),查了好久,没想到&的优先级这么低
}
}
void solve(){
int i,j,k,p,ans=0;
for(i=2;i<N+2;i++)
for(j=0;j<cnt[i];j++)
for(k=0;k<cnt[i-1];k++)
for(p=0;p<cnt[i-2];p++)
if((state[i][j]&state[i-1][k])==0&&(state[i][j]&state[i-2][p])==0&&(state[i-1][k]&state[i-2][p])==0)
dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][p]+can[i][j]);
for(j=0;j<cnt[N+1];j++)
for(k=0;k<cnt[N];k++)
ans=max(ans,dp[N+1][j][k]);
printf("%d\n",ans);
}
int main(){
int i;
scanf("%d%d",&N,&M);
for(i=0;i<N;i++)scanf("%s",map[i]);
memset(cnt,0,sizeof(cnt)),memset(tmp2,0,sizeof(tmp2)),memset(dp,0,sizeof(dp));
init();
solve();
return 0;
}
//P2704 [NOI2001]炮兵阵地
//在线测评地址https://www.luogu.org/problemnew/show/P2704
//发现,还是可以用状压dp的,先摸索,争取能弄出AC。
//第一步,计算每一行,可能的炮兵放置
//对左移,右移,运算符,还不是太熟,编码后才了解了。
//i<<1左移1位,i<<2左移2位,i>>1右移1位,i>>2右移2位,看到了吗,移动的位数一定放在右边。
//测试了,发现M=10,不考虑山,符合条件的有60个,故,数组在状态处,开到100即可
//if((tmp[j]&b)==0)state[i][cnt[i]]=tmp[j],cnt[i]++,printf("%d tmp%d\n",i,tmp[j]);//此处写成if(tmp[j]&b==0),查了好久,没想到&的优先级这么低
//搜索网络,发现,确实如此。
//写dp时,感觉思路有点乱,还是先停一停,想清楚了,再来。
//在dp的维度上想了很久,跨度一天,还是相通了,感觉很好。
//样例通过,提交20分,测试点2-9WA。2019-3-14
//什么地方有问题,
//以下为20分代码。
//经过长时间的思考,dp[i][j]=max(dp[i][j],can[i][j]+can[i-1][k]+dp[i-2][p]);发现can[i-1][k]有可能会与dp[i-3][q]冲突
//故上述转移方程错误。2019-3-15 19:23
#include <stdio.h>
#include <string.h>
int N,M,tmp[100],num=0,state[105][100],cnt[100],dp[105][100],can[105][100],tmp2[100];//can[i][j]对应i行,j状态,部队数量。dp[i][j] 对应i行,状态j的最多部队数量
char map[105][12];
int max(int a,int b){
return a>b?a:b;
}
void init(){
int i,j,tot,b;
tot=(1<<M)-1;
for(i=0;i<=tot;i++)
if(((i<<1)&i)==0&&((i<<2)&i)==0&&((i>>1)&i)==0&&((i>>2)&i)==0)//先筛出枚举的可能
tmp[num]=i,num++;
for(i=0;i<num;i++){
j=tmp[i];
while(j){
if(j&1)tmp2[i]++;//部队数量
j>>=1;
}
}
state[0][0]=0,can[0][0]=0,cnt[0]=1,state[1][0]=0,can[1][0]=0,cnt[1]=1;//为了方便处理数据,添加2行
for(i=2;i<N+2;i++){
b=0;
for(j=0;j<M;j++)
if(map[i][j]=='H')
b|=(1<<j);
for(j=0;j<num;j++)
if((tmp[j]&b)==0)state[i][cnt[i]]=tmp[j],can[i][cnt[i]]=tmp2[j],cnt[i]++;//此处写成if(tmp[j]&b==0),查了好久,没想到&的优先级这么低
}
}
void solve(){
int i,j,k,p,ans=0;
dp[0][0]=0,dp[1][0]=0;
for(i=2;i<N+2;i++)
for(j=0;j<cnt[i];j++)
for(k=0;k<cnt[i-1];k++)
for(p=0;p<cnt[i-2];p++)
if((state[i][j]&state[i-1][k])==0&&(state[i][j]&state[i-2][p])==0&&(state[i-1][k]&state[i-2][p])==0)
dp[i][j]=max(dp[i][j],can[i][j]+can[i-1][k]+dp[i-2][p]);
for(j=0;j<cnt[N+1];j++)ans=max(ans,dp[N+1][j]);
printf("%d\n",ans);
}
int main(){
int i;
scanf("%d%d",&N,&M);
for(i=0;i<N;i++)scanf("%s",map[i]);
memset(cnt,0,sizeof(cnt)),memset(tmp2,0,sizeof(tmp2)),memset(dp,0,sizeof(dp));
init();
solve();
return 0;
}
9.dp:2017: [Usaco2009 Nov]硬币游戏
10.dfs:[Usaco2005 Feb]Rigging the Bovine Election 竞选划区
11.暴力:1661: [Usaco2006 Nov]Big Square 巨大正方形
12.tarjan:1654: [Usaco2006 Jan]The Cow Prom 奶牛舞会
13.dp+矩阵乘法:A:Quad Tiling
14.线段树:B:Garden
15.模拟:D:One-move checkmate
16.二分+贪心:E:ATP
17.费用流:「bzoj3308」九月的咖啡店
Codeforces Round #161 (Div. 2)
18.模拟:A.Beautiful Matrix
19.模拟:B. Squares
20.dfs:C. Circle of Numbers
21.dfs:D.Cycle in Graph
22.模拟:E. Rhombus
2015全国互测 3
23.排列组合:Country
24.「百度之星」数长方形 暴力
25.「百度之星」最强密码 暴力
26.「百度之星」大搬家 dp