zoukankan      html  css  js  c++  java
  • 学校作业-Dp练习


    题目


    ★Stringsobits01 串 
    考虑排好序的 N(N<=31)位二进制数. 
    你会发现,这很有趣.因为他们是排列好的,而且包含所有可能的长度为 N 且含有 1 的个数小于等于
    L(L<=N)的数. 
    你的任务是输出第 I(1<=I<=长度为 N 的二进制数的个数)大的,长度为 N,且含有 1 的个数小于等
    于 L 的那个二进制数. 
    PROGRAM NAME: kimbits 
    INPUT FORMAT
    共一行,用空格分开的三个整数 N,L,I. 
    SAMPLE INPUT (file kimbits.in) 
    5 3 19 
    OUTPUT FORMAT

    共一行,输出满足条件的第 I 大的二进制数. 

    SAMPLE OUTPUT (file kimbits.out) 
    10011 


    题解


    这道题吧,我觉得就是一位一位试,如果当前填0,用组合数计算一下共有多少个数字,如果小于i的话,当前就填1,否则就填0,一直试下去就可以了。我猜它可以数位DP?没仔细想QAQ


    代码


    /*Author:WNJXYK*/
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    using namespace std;
    
    #define LL long long
    
    inline void swap(int &x,int &y){int tmp=x;x=y;y=tmp;}
    inline void swap(LL &x,LL &y){LL tmp=x;x=y;y=tmp;}
    inline int remin(int a,int b){if (a<b) return a;return b;}
    inline int remax(int a,int b){if (a>b) return a;return b;}
    inline LL remin(LL a,LL b){if (a<b) return a;return b;}
    inline LL remax(LL a,LL b){if (a>b) return a;return b;}
    
    LL n,l,m;
    int Ans[40];
    LL Pow[32];
    inline LL getC(int n,int m){
    	LL Ans=1;
    	if (n-m>m) m=n-m;
    	for (int i=m+1;i<=n;i++) Ans*=i;
    	for (int i=2;i<=n-m;i++) Ans/=i;
    	return Ans;
    }
    inline LL getCS(int n,int m){
    	LL Ans=1;
    	for (int i=1;i<=m;i++) Ans+=getC(n,i);
    	return Ans;
    }
    int main(){
    	scanf("%lld%lld%lld",&n,&l,&m);
    	for (int i=n;i>=2;i--){
    		LL tmp=getCS(i-1,remin(i-1,(int)l));
    		if (tmp<m){
    			m-=tmp;
    			Ans[i]=1;
    			l-=1;
    		}else{
    			Ans[i]=0;
    		}
    	}
    	Ans[1]=!(m==1);
    	bool isOne=false;
    	for (int i=n;i>=1;i--){
    		isOne=isOne||Ans[i];
    		if (isOne) printf("%d",Ans[i]);
    	}
    	printf("
    ");
    	return 0;
    }
    

    题目


    ★Raucous Rockers“破锣摇滚”乐队 
    你刚刚继承了流行的“破锣摇滚”乐队录制的尚未发表的 N(1 <= N <= 20)首歌的版权.你打算从
    中精选一些歌曲,发行 M(1 <= M <= 20)张 CD.每一张 CD 最多可以容纳 T(1 <= T <= 20)分钟的音
    乐,一首歌不能分装在两张 CD 中. 
    不巧你是一位古典音乐迷,不懂如何判定这些歌的艺术价值.于是你决定根据以下标准进行选择: 
    歌曲必须按照创作的时间顺序在 CD 盘上出现. 选中的歌曲数目尽可能地多. 
    PROGRAM NAME: rockers 
    INPUT FORMAT
    第一行: 三个整数:N, T, M. 
    第二行: N 个整数,分别表示每首歌的长度,按创作时间顺序排列. 
    SAMPLE INPUT (file rockers.in) 
    4 5 2 
    4 3 4 2 
    OUTPUT FORMAT
    一个整数,表示可以装进 M 张 CD 盘的乐曲的最大数目. 
    SAMPLE OUTPUT (file rockers.out) 


    题解


    这道题目我调了好长时间,我自我检讨QAQ,因为太困了【鬼信你啊!好吧,f[i][j]={a,b}表示前i个歌曲装j首,最少需要a个光碟,并且那种情况下最后一张光碟剩余b分钟之间。这样从f[i-1][j]和f[i-1][j-1]随便转移就好了!


    代码


    /*Author:WNJXYK*/
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    using namespace std;
    
    #define LL long long
    
    inline void swap(int &x,int &y){int tmp=x;x=y;y=tmp;}
    inline void swap(LL &x,LL &y){LL tmp=x;x=y;y=tmp;}
    inline int remin(int a,int b){if (a<b) return a;return b;}
    inline int remax(int a,int b){if (a>b) return a;return b;}
    inline LL remin(LL a,LL b){if (a<b) return a;return b;}
    inline LL remax(LL a,LL b){if (a>b) return a;return b;}
    
    int n,t,m;
    int ti[25];
    struct Node{
    	int index;
    	int left;
    	Node(){index=left=2147483647;}
    	Node(int a,int b){index=a;left=b;};
    	void update(Node x){
    		int i=x.index;
    		int l=x.left;
    		if (i<index){
    			index=i;
    			left=l;
    		}else if (i==index && l<left){
    			left=l;
    		}
    	}
    	void update_new(Node x,int xt){
    		update(Node(x.index+1,t-xt));
    		if (x.left-xt>=0) update(Node(x.index,x.left-xt));
    	}
    };
    Node f[25][25];
    
    int main(){
    	scanf("%d%d%d",&n,&t,&m);
    	for (int i=1;i<=n;i++) scanf("%d",&ti[i]);
    	f[0][0].index=0;
    	f[0][0].left=t;
    	int min=2147483647;
    	for (int i=1;i<=n;i++){
    		for (int j=1;j<=i;j++){
    			f[i][j].update(f[i-1][j]);
    			f[i][j].update_new(f[i-1][j-1],ti[j]);
    		}
    	}
    	int Ans=0;
    	for (int i=1;i<=n;i++)if (f[n][i].index<=m) Ans=i;
    	printf("%d
    ",Ans);
    	return 0;
    }
    

    题目


    ★Canada Tour 周游加拿大 
    你赢得了一场航空公司举办的比赛,奖品是一张加拿大环游机票.旅行在这家航空公司开放的最西
    边的城市开始,然后一直自西向东旅行,直到你到达最东边的城市,再由东向西返回,直到你回到开
    始的城市.每个城市只能访问一次,除了旅行开始的城市之外,这个城市必定要被访问两次(在旅行
    的开始和结束).你不允许使用其他公司的航线或者用其他的交通工具. 
    给出这个航空公司开放的城市的列表,和两两城市之间的直达航线列表.找出能够访问尽可能多的
    城市的路线,这条路线必须满足上述条件,也就是从列表中的第一个城市开始旅行,访问到列表中最
    后一个城市之后再返回第一个城市. 
    PROGRAM NAME: tour 
    INPUT FORMAT
    Line 1: 航空公司开放的城市数 N 和将要列出的直达航线的数量 V.N 是一个不大于 100 的

    正整数.V 是任意的正整数. 
    Lines 2..N+1: 每行包括一个航空公司开放的城市名称.城市名称按照自西向东排列.不会出
    现两个城市在同一条经线上的情况.每个城市的名称都是一个字符串,最多 15 字节,由拉丁字母表
    上的字母组成;城市名称中没有空格. 
    Lines N+2..N+2+V-1: 每行包括两个城市名称(由上面列表中的城市名称组成),用一个空格分开.
    这样就表示两个城市之间的直达双程航线. 
    SAMPLE INPUT (file tour.in) 
    8 9 
    Vancouver 
    Yellowknife 
    Edmonton 
    Calgary 
    Winnipeg 
    Toronto 
    Montreal 
    Halifax 
    Vancouver Edmonton 
    Vancouver Calgary 
    Calgary Winnipeg 
    Winnipeg Toronto 
    Toronto Halifax 
    Montreal Halifax 
    Edmonton Montreal 
    Edmonton Yellowknife 
    Edmonton Calgary 
    OUTPUT FORMAT
    Line 1: 按照最佳路线访问的不同城市的数量 M.如果无法找到路线,输出 1. 
    SAMPLE OUTPUT (file tour.out) 

    也就是: Vancouver, Edmonton, Montreal, Halifax, Toronto, Winnipeg, Calgary, 和 Vancouver 
    (回到开始城市,但是不算在不同城市之内). 


    题解


    这里我们反向返回的边,就变成了求两个不同路径。我们使用f[i][j]表示两个人一个到第i个城市,一个到第j个城市的经过城市数量。我们在转移的时候时刻保证i<j这样我们有一条k->j的边一定可以保证没有在f[i][k]中走过,因为f[i][k]还没有考虑j这个点。然后我们有对称性可知,f[i][j]=f[j][i]就这样愉快的一直推,最后找到最大的f[i][n]就可以了!


    代码


    /*Author:WNJXYK*/
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    
    #define LL long long
    
    inline void swap(int &x,int &y){int tmp=x;x=y;y=tmp;}
    inline void swap(LL &x,LL &y){LL tmp=x;x=y;y=tmp;}
    inline int remin(int a,int b){if (a<b) return a;return b;}
    inline int remax(int a,int b){if (a>b) return a;return b;}
    inline LL remin(LL a,LL b){if (a<b) return a;return b;}
    inline LL remax(LL a,LL b){if (a>b) return a;return b;}
    
    map<string,int> city;
    bool g[105][105];
    int f[105][105];
    int n,m;
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++){
    		string tmp;
    		cin>>tmp;
    		city[tmp]=i;
    	}
    	for (int i=1;i<=m;i++){
    		string tmp1,tmp2;
    		cin>>tmp1>>tmp2;
    		g[city[tmp1]][city[tmp2]]=g[city[tmp2]][city[tmp1]]=true;
    	}
    	f[1][1]=1;
    	for (int i=1;i<=n;i++){
    		for (int j=i+1;j<=n;j++){
    			for (int k=1;k<j;k++){
    				if (g[k][j] && f[i][k]>0 && f[i][k]+1>f[i][j]) f[i][j]=f[j][i]=f[i][k]+1;
    			}
    		}
    	}
    	int Ans=1;
    	for (int i=1;i<=n;i++){
    		if (g[i][n] && f[i][n]>Ans) Ans=f[i][n];
    	}
    	printf("%d
    ",Ans);
    	return 0;
    }
    


    P.S.今天的作业做得略慢啊!BZOJ还剩48次提交,用完它!

  • 相关阅读:
    aspnet中存储session的各种方法
    Response.ContentType 详细列表
    常用命令行命令
    关于使用request[this.控件名.Unique]获取控件值的问题
    在Asp.net中动态添加css文件,js文件,控件
    关于.Net中垃圾回收机制的理解:
    简单概念
    天健
    (转)高效调用lua函数
    (转)hlsl函数
  • 原文地址:https://www.cnblogs.com/WNJXYK/p/4063931.html
Copyright © 2011-2022 走看看