考察知识:队列,模拟
算法难度:X+ 实现难度:X+
分析:真的很简单,直接按照题意模拟即可
代码:
#include
int n,m,que[1005],L,R,cnt=0,k;
int main(){
scanf("%d%d",&m,&n);
while(n--){
bool find=false;
scanf("%d",&k);
for(int i=L;im) L++;
}
printf("%d\n",cnt);
return 0;
}
考察知识:动态规划
算法难度:XXX 实现难度:XX+
分析:如果想出了状态转移方程就简单了,但是想不出,那就......
注意到只有四种卡片
定义状态方程:f[i][j][k][l]表示分别用i,j,k,l张数字分别为1,2,3,4的卡片所能得到的最大分数
代码:
#include
#define F(var,L,R) for(int var=L;var<=R;var++)
#define Max(var,var_) var=var>(var_)?var:(var_)
int p[355],m,n,card[5],k,f[42][42][42][42];
int main(){
scanf("%d%d",&n,&m);
F(i,1,n) scanf("%d",p+i);
F(i,1,m) scanf("%d",&k),card[k]++;
F(i,0,card[1]) F(j,0,card[2])
F(k,0,card[3]) F(l,0,card[4]){
int pos=i+j*2+k*3+l*4+1;
if(i) Max(f[i][j][k][l],f[i-1][j][k][l]);
if(j) Max(f[i][j][k][l],f[i][j-1][k][l]);
if(k) Max(f[i][j][k][l],f[i][j][k-1][l]);
if(l) Max(f[i][j][k][l],f[i][j][k][l-1]);
f[i][j][k][l]+=p[pos];
}
printf("%d\n",f[card[1]][card[2]][card[3]][card[4]]);
return 0;
}
考察知识:二分图的判定,二分
算法难度:XXX 实现难度:XXX
分析:二分怨气值,假设怨气值小于等于mid,那么我们要把所有怨气值小于等于mid的边全部忽略,然后判断剩下的图是否为二分图
代码:
#include
#include
const int maxn=200005;
struct edge{
int to,next,w;
}e[maxn*10];
int head[maxn],np,c[maxn];
void add(int u,int v,int w){
e[++np]=(edge){v,head[u],w};
head[u]=np;
}
int n,m;
bool dfs(int i,int C,int limt){
c[i]=C;
for(int p=head[i];p;p=e[p].next) if(e[p].w>limt){
int j=e[p].to;
if(c[j]){
if(c[j]==c[i]) return false;
}
else if(!dfs(j,-C,limt)) return false;
}
return true;
}
void build(){
int u,v,w;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w),add(v,u,w);
}
}
bool check(int limt){
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++) if(!c[i]&&!dfs(i,1,limt))
return false;
return true;
}
void solve(){
int l=0,r=1000000000,ans;
while(l<=r){
int mid=(l+r)/2;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
}
int main(){
build();
solve();
return 0;
}
考察知识:搜索,bfs,区间覆盖,贪心
算法难度:XXXX 实现难度:XXX+
分析:我们首先bfs判断干旱区是否满足全部可以建水利设施,如果可以,
我们枚举第一行的每一个格子i,可以证明:只在i建蓄水厂,那么干旱区可以建水利设施的地方一定是一段连续区间
如果你想到这一点了,那么基本上就解决这道题了,剩下的就是转化为区间覆盖问题然后解决,我们常常用贪心算法解决
代码:
#include
#include
#include
#include
using namespace std;
struct line{
int l,r;
line(){l=r=0;}
friend bool operator < (line A,line B){
return A.lq;
vis[x][y]=true;
int nx,ny;
q.push(x),q.push(y);
while(!q.empty()){
x=q.front(),q.pop();
y=q.front(),q.pop();
for(int i=0;i<4;i++){
nx=x+dx[i],ny=y+dy[i];
if(nx<1||nx>n||ny<1||ny>m||a[nx][ny]>=a[x][y]
||vis[nx][ny]) continue;
vis[nx][ny]=true;
q.push(nx),q.push(ny);
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=m;i++) bfs(1,i);
int cnt=0;
for(int i=1;i<=m;i++) if(!vis[n][i]) cnt++;
if(cnt){printf("0\n%d",cnt);return 0;}//判断是否满足要求
for(int i=1;i<=m;i++){
memset(vis,0,sizeof(vis));
bfs(1,i);
for(int k=1;k<=m;k++) if(vis[n][k]){//生成区间
l[i].l=k;break;
}
for(int k=m;k>0;k--) if(vis[n][k]){
l[i].r=k;break;
}
}
sort(l+1,l+m+1);
int L=1,k=1;
while(k<=m&&L<=m){//区间覆盖问题
int tmp=-1;
while(k<=m&&l[k].l<=L){
if(l[k].r>tmp) tmp=l[k].r;
k++;
}
cnt++,L=tmp+1;
}
printf("1\n%d",cnt);
return 0;
}