飞扬的小鸟

                                                                                飞扬的小鸟

这一题开始看到时就知道是DP,但作死打了个dfs,只有75分……

//卡常大法好
#include<bits/stdc++.h>
using namespace std;
const int N = 10005;
const int inf = 9999999;
int g_sum[N],g_up[N],g_down[N],up[N],down[N],n,m,k,f[N][1005],ff,p,l,h,ans,anss=inf;
inline void dfs(int x,int y,int o){
    if(o>=anss)return;
    if(y>m) y=m;
    if(y<=0)return;
    if(y>=g_up[x]||y<=g_down[x]) return;
    if(f[x][y]<=o) return;
    f[x][y]=o;
    if(x>=n){
        ff=1;
        anss=min(anss,o);
        return;
    }
    dfs(x+1,y-down[x],o);
    for(register int i=1;y+i*up[x]<=m+up[x];i++)	
    dfs(x+1,y+up[x]*i,o+i);
    
}
int main()
{
 	scanf("%d%d%d",&n,&m,&k);
 	for(register int i=0;i<=n+1;i++)
        for(register int j=1;j<=m;j++) f[i][j]=inf;
    for(register int i=0;i<=n;i++) g_up[i]=m+1;
 	for(register int i=0;i<n;i++) scanf("%d%d",&up[i],&down[i]);
 	for(register int i=1;i<=k;i++){
 		scanf("%d%d%d",&p,&l,&h);
        g_up[p]=h;
        g_down[p]=l;
     } 
     for(register int i=1;i<=n;i++){
     	g_sum[i]=g_sum[i-1];
     	if(g_up[i]!=m+1||g_down[i]) g_sum[i]++;
     }
     for(register int i=1;i<=m;i++){
     	dfs(0,i,0);
     }
     printf("%d\n",ff);
     if(ff){
     	ans=inf;
     	for(register int i=1;i<=m;i++) ans=min(ans,f[n][i]);
     	printf("%d",ans);
     }else{
     	for(register int i=n;i>=1;i--){
     		for(register int j=1;j<=m;j++){
     			if(f[i][j]!=inf){
     				printf("%d",g_sum[i]);
     				return 0;
                 }
             }
         }
     }
   return 0;
}

"剪枝减去我们的(到我们)疯狂……”

快疯掉了,然后打了一波DP,维护把三重循环优化成了两重,

上吧,我的代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 10005;
const int inf = 9999999;
int g_sum[N],g_up[N],g_down[N],up[N],down[N],n,m,k,f[N][1005],ff,p,l,h,ans,anss=inf,fa[N];
void work(){
	for(register int i=1;i<=n;i++){
		for(register int j=1;j<=m;j++) fa[j]=inf;
		int dow=down[i-1];
		int u=up[i-1];
		for(register int j=1;j<=m;j++){
			if(j-u<g_up[i-1]&&j-u>g_down[i-1])fa[j]=min(fa[j],f[i-1][j-u]+1);
			if(j+dow<g_up[i-1]&&j+dow>g_down[i-1])f[i][j]=min(f[i][j],f[i-1][j+dow]);
			if(j-u<g_up[i-1]&&j-u>g_down[i-1]) f[i][j]=min(f[i][j],f[i-1][j-u]+1);
			if(j-u>0)f[i][j]=min(f[i][j],fa[j-u]+1);
			if(j-u>0)fa[j]=min(fa[j],fa[j-u]+1);
		}
		for(register int j=m;j<=m+u;j++){
			if(j-u<g_up[i-1]&&j-u>g_down[i-1]) f[i][m]=min(f[i][m],f[i-1][j-u]+1);
			if(j-u>0)f[i][m]=min(f[i][m],fa[j-u]+1);
		}
	}
	for(int i=1;i<=m;i++) if(f[n][i]!=inf) ff=1;
}
int main()
{
 	scanf("%d%d%d",&n,&m,&k);
 	for(register int i=0;i<=n+1;i++)
		for(register int j=1;j<=m;j++) f[i][j]=inf;
    for(register int i=0;i<=n;i++) g_up[i]=m+1;
 	for(register int i=0;i<n;i++) scanf("%d%d",&up[i],&down[i]);
 	for(register int i=1;i<=k;i++){
 		scanf("%d%d%d",&p,&l,&h);
	    g_up[p]=h;
	    g_down[p]=l;
	 } 
	 for(register int i=1;i<=n;i++){
	 	g_sum[i]=g_sum[i-1];
	 	if(g_up[i]!=m+1||g_down[i]) g_sum[i]++;
	 }
	 for(register int i=1;i<=m;i++)	f[0][i]=0;
	 work();
	 printf("%d\n",ff);
	 if(ff){
	 	ans=inf;
	 	for(register int i=1;i<=m;i++) ans=min(ans,f[n][i]);
	 	printf("%d",ans);
	 }else{
	 	for(register int i=n;i>=1;i--){
	 		for(register int j=1;j<=m;j++){
	 			if(f[i][j]!=inf&&j<g_up[i]&&j>g_down[i]){
	 				printf("%d",g_sum[i]);
	 				return 0;
				 }
			 }
		 }
	 }
   return 0;
}

posted @ 2018-06-18 14:40  lahlah  阅读(36)  评论(0编辑  收藏  举报