zoukankan      html  css  js  c++  java
  • 专题:DP杂题1

    A POJ 1018 Communication System
    B POJ 1050 To the Max
    C POJ 1083 Moving Tables
    D POJ 1125 Stockbroker Grapevine
    E POJ 1143 Number Game
    F POJ 1157 LITTLE SHOP OF FLOWERS
    G POJ 1163 The Triangle
    H POJ 1178 Camelot
    I POJ 1179 Polygon
    J POJ 1189 钉子和小球
    K POJ 1191 棋盘分割
    L POJ 1208 The Blocks Problem
    M POJ 1276 Cash Machine
    N POJ 1322 Chocolate
    O POJ 1414 Life Line
    P POJ 1456 Supermarket
    Q POJ 1458 Common Subsequence
    R POJ 1609 Tiling Up Blocks
    S POJ 1644 To Bet or Not To Bet
    T POJ 1664 放苹果
    U POJ 1690 (Your)((Term)((Project)))
    V POJ 1699 Best Sequence
    W POJ 1740 A New Stone Game
    X POJ 1742 Coins
    Y POJ 1887 Testing the CATCHER
    Z POJ 1926 Pollution

    点击题号进入题面

    ---

    A

    /*
    dp[i,j]
    i个设备
    j最小带宽
    只能转移到dp[i-1][j]+大于等于j带宽的设备
    */
    #include <stdio.h>
    #include <math.h>
    #include <iostream>
    #include <string.h>
    using namespace std;
    const int maxn=1e3+10;
    const int maxm=1e6+10;
    const int INF=0x3f3f3f3f;
    int casn,n,m,k;
    int dp[maxn][maxn];
    int num[maxn];
    int p[maxn][maxn],f[maxn][maxn];
    int main(){
    //#define test
    #ifdef test
    	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    
    	cin>>casn;
    	while(casn--){
    		int mx=0;
    		cin>>n;
    		for(int i=1;i<=n;i++){
    			cin>>num[i];
    			for(int j=1;j<=num[i];j++){
    				cin>>f[i][j]>>p[i][j];
    				mx=max(f[i][j],mx);
    			}
    		}
    		memset(dp,0,sizeof dp);
    		for(int i=1;i<=n;i++){
    			for(int j=0;j<=mx;j++){
    				int mn=INF;
    				for(int k=1;k<=num[i];k++){
    					if(j<=f[i][k]){
    						mn=min(dp[i-1][j]+p[i][k],mn);
    					}
    				}
    				dp[i][j]=mn;
    			}
    		}
    		double ans=0;
    		for(int i=1;i<=mx;i++){
    			ans=max(ans,i/(double)dp[n][i]);
    		}
    		printf("%.3f
    ",ans);
    	}
    #ifdef test
    	fclose(stdin);fclose(stdout);system("out.txt");
    #endif
    	return 0;
    }
    

    B

    /*
    把二维看成一维
    先枚举行的起点和终点
    再把起点行和终点行间每一列的数值压缩到每一个点上
    然后求一个最长连续字段和
    复杂度O(n^3)
    */
    #include <string.h>
    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=1e3+10;
    const int maxm=1e6+10;
    const int INF=0x3f3f3f3f;
    #define ll long long
    int casn,n,m,k;
    int smax(int a[],int len){
    	int mx=0,sub=0;
    	for(int i=1;i<=len;i++){
    		sub=max(a[i],sub+a[i]);
    		mx=max(sub,mx);
    	}
    	return mx;
    }
    int arr[maxn];
    int dp[maxn][maxn];
    int main(){
    #define test
    #ifdef test
    	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    
    	while(~scanf("%d",&n)){
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n;j++){
    				scanf("%d",&dp[i][j]);
    			}
    		}
    		int ans=-INF;
    		for(int i=1;i<=n;i++){
    			memset(arr,0,sizeof arr);
    			for(int j=i;j<=n;j++){
    				for(int k=1;k<=n;k++){
    					arr[k]+=dp[j][k];
    				}
    				ans=max(ans,smax(arr,n));
    			}
    		}
    		printf("%d
    ",ans);
    	}
    #ifdef test
    	fclose(stdin);fclose(stdout);system("out.txt");
    #endif
    	return 0;
    }
    

    C

    /*
    交叉的工作是必须要完成的
    而所有的不交叉工作都可以同时完成
    那最晚完成的就是交叉次数最多的走廊区域了
    注意由于走廊是公用的,所以南北的房间实际上一样
    映射到1-200的区域就行了
    */
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    const int maxn=1e3+10;
    const int maxm=1e6+10;
    const int INF=0x3f3f3f3f;
    int casn,n,m,k;
    int cost[maxn];
    int main(){
    // #define test
    #ifdef test
    	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    
    	scanf("%d",&casn);
    	while(casn--){
    		scanf("%d",&n);
    		memset(cost,0,sizeof cost);
    		for(int i=1;i<=n;i++){
    			int x,y;
    			scanf("%d%d",&x,&y);
    			if(x>y) swap(x,y);
    			x=(x>>1)+(x&1);
    			y=(y>>1)+(y&1);
    			for(int j=x;j<=y;j++){
    				cost[j]++;
    			}
    		}
    		int ans=0;
    		for(int i=1;i<=400;i++){
    			ans=max(cost[i],ans);
    		}
    		printf("%d
    ",ans*10);
    	}
    
    #ifdef test
    	fclose(stdin);fclose(stdout);system("out.txt");
    #endif
    	return 0;
    }
    

    D

    /*
    有向图的floyd
    跑完之后枚举一遍起点
    保存最小最长边
    输出的时候特判一下
    */
    #include <string.h>
    #include <algorithm>
    #include <stdio.h>
    using namespace std;
    const int maxn=1e2+10;
    const int maxm=1e6+10;
    const int INF=0x3f3f3f3f;
    int casn,n,m,k;
    int num[maxn];
    int dp[maxn][maxn];
    int main(){
    //#define test
    #ifdef test
    	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    
    	while(scanf("%d",&n),n){
    		memset(dp,INF,sizeof dp);
    		for(int i=1;i<=n;i++){
    			scanf("%d",&num[i]);
    			for(int j=0;j<num[i];j++){
    				int a,b;
    				scanf("%d%d",&a,&b);
    				dp[i][a]=b;
    			}
    		}
    		for(int k=1;k<=n;k++){
    			for(int i=1;i<=n;i++){
    				for(int j=1;j<=n;j++){
    					int t=dp[i][k]+dp[k][j];
    					dp[i][j]=min(dp[i][j],t);
    				}
    			}
    		}
    		int flag=0,ans=INF,id=0;
    		for(int i=1;i<=n;i++){
    			int t=0;
    			for(int j=1;j<=n;j++){
    				if(i==j) continue;
    				t=max(t,dp[i][j]);
    			}
    			if(t<ans) id=i,ans=t;
    		}
    		if(!id) puts("disjoint");
    		else printf("%d %d
    ",id,ans);
    	}
    	
    #ifdef test
    	fclose(stdin);fclose(stdout);system("out.txt");
    #endif
    	return 0;
    }
    

    E

    /*
    如果i在list里,则进行dfs
    如果dfs可以推出失败.则保存答案
    dfs:
      状态很显然是20个数字那些不能选
    	状态种类不多且每个状态只有2种情况
    	考虑状态压缩,每一位保存该位置的数字是否可以使用
    	用记忆化搜索,标记2进制所保存的状态的输赢
    	不断dfs,换选手,返回下一个选手是输还是赢即可
    	如果下一个选手输,则当前为必胜态,以此类推
    */
    #include <string.h>
    #include <algorithm>
    #include <stdio.h>
    using namespace std;
    const int maxn=2e6+10;
    const int maxm=1e6+10;
    const int INF=0x3f3f3f3f;
    int casn,n,m,k;
    int num[30];
    int dp[maxn];
    bool vis[30];
    int ans[30];
    int cps(bool vis[]){
    	int stt=0;
    	for(int i=2;i<=20;i++){
    		stt|=vis[i];
    		stt<<=1;
    	}
    	return stt>>1;
    }
    bool dfs(int now,bool vis[]){
    	bool vis2[30];
    	memcpy(vis2,vis,25);
    	vis2[now]=false;
    	for(int i=2;i+now<=20;i++){
    		if(!vis2[i])vis2[i+now]=false;
    	}
    	int stt=cps(vis2);
    	if(dp[stt]){
    		return dp[stt]>0;
    	}
    	for(int i=2;i<=20;i++){
    		if(vis2[i]&&!dfs(i,vis2)) return dp[stt]=1;
    	}
    	dp[stt]=-1;
    	return false;
    }
    int main(){
    //#define test
    #ifdef test
    	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    	memset(dp,0,sizeof dp);
    	while(scanf("%d",&n),n){
    		memset(vis,0,sizeof vis);
    		for(int i=1;i<=n;i++){
    			scanf("%d",&num[i]);
    			vis[num[i]]=true;
    		}
    		int cnt=0;
    		int stt=cps(vis);
    		for(int i=2;i<=20;i++){
    			if(vis[i]&&!dfs(i,vis)) ans[cnt++]=i;
    		}
    		printf("Test Case #%d
    ",++casn);
    		if(cnt){
    			printf("The winning moves are:");
    			for(int i=0;i<cnt;i++){
    				printf(" %d",ans[i]);
    			}
    			puts("");
    		}else dp[stt]=-1,puts("There's no winning move.");
    		puts("");
    	}
    	
    #ifdef test
    	fclose(stdin);fclose(stdout);system("out.txt");
    #endif
    	return 0;
    }
    

      

  • 相关阅读:
    光流法简单介绍
    learn something
    MOT
    jupyter notebook 启动出错
    SSD用测试集得到具体的检测结果
    百练_2677 肿瘤检测
    百练_2707 求一元二次方程的根
    百练_4022 买房子
    HDU2035 人见人爱A^B(快速幂)
    BestCoder Round #85 sum
  • 原文地址:https://www.cnblogs.com/nervendnig/p/8620950.html
Copyright © 2011-2022 走看看