zoukankan      html  css  js  c++  java
  • 8.8&8.9 dp训练小结

    写了两天的dp题,表示大多dp都不会啊,还是爆搜大法好。我真的太蒻了dp还是要多做题啊,一些基本的套路还是不熟,真正写对的dp也就一道,还一道爆搜过的,dp还有很深的坑要填啊。。

    8.8

    T1 质数和式

    题意

    大概就是给出一个数n,用质数将它表示按字典序由大到小排序,输出排列为k的质数和式

    解析


    代码(咕咕)

    T2 终极简单问题

    假的终极简单

    解析

    挂上学长的题解

    代码(继续咕咕)

    T3 分宝藏

    题意


    一道比较有趣的题,等有时间写吧。

    代码(继续吧)

    T4 取数字问题

    题意

    sb题目,不多说,爆搜就能过。

    代码(这个总算没咕咕)

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,ans=1<<30,a[15][15];
    void dfs(int x,int y,int data){
    	if(x==n&&y==m){
    		if(data>0){
    			ans=min(ans,data);
    			return;
    		}
    	}
    	if(x+1<=n&&y<=m) dfs(x+1,y,data+a[x+1][y]);
    	if(x<=n&&y+1<=m) dfs(x,y+1,data+a[x][y+1]);
    }
    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]);
    		}
    	}
    	dfs(1,1,a[1][1]);
    	if(ans==(1<<30)) printf("-1");
    	else printf("%d",ans);
    	return 0;
    }
    

    正解据说是这样的

    T5 求三角形最大的面积

    题意



    爆搜拿了40多分。。。

    解析

    代码(马上就补)

    8.9

    T1 可怜的绵羊

    题意



    一道比较神仙的题目,做法看解析吧,考场输出die个get 13 point

    代码(还毛写,先放std)

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    using namespace std;
    #define maxn 101
     
    struct point {
        long long x,y;
    };
    long long n,m=0;
    //凸多边形顶点坐标和内部点的坐标
    point vertex[maxn],insd[maxn];
    //检查点是否在多边形边上
    int out[maxn][maxn],online[maxn][maxn];
     
    //默认的abs函数是对整数取绝对值
    long long abs(long long x){
        return x<0 ? -x : x;
    }
     
    //返回三角形abc面积的两倍
    long long area(point a,point b,point c){
        return abs(a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y));
    }
     
    //向量oa叉乘向量ob
    //大于0,这三个点是逆时针;小于0,这三个点是顺时针
    long long multiple(point a,point b,point o){
        return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
    }
     
    void prepare(){
        long i,j,k,tmp;
        memset(out,0,sizeof(out));
        memset(online,0,sizeof(online));
        for (i=1;i<=n;i++)
            for (j=1;j<=n;j++)
                if (i!=j)
                    for (k=1;k<=m;k++){
                        tmp=multiple(insd[k],vertex[j],vertex[i]);
                        if (tmp>=0) out[i][j]++; //判断是否在逆时针方向
                        if (tmp==0) online[i][j]=1;
                    }
    }
     
    void dp(){
        long long u,i,j;
        long long a[maxn],tmp,max=0;
        //枚举点u,并求出最大值
        for (u=1;u<=n-2;u++){
            memset(a,0,sizeof(a));
            for (i=u+1;i<=n-1;i++)
                for (j=i+1;j<=n;j++)
                    //判断三角形内是否有点
                    if (out[u][i]+out[i][j]+out[j][u]==m) {
                        //更新a[j]的值,取最大值
                        tmp=area(vertex[u],vertex[i],vertex[j]);
                        if (tmp>a[j]) a[j]=tmp;
                        if (online[u][i]==0) {
                            tmp+=a[i];
                            if (tmp>a[j]) a[j]=tmp;
                        }
                    }
            for (j=u+2;j<=n;j++)
                if (a[j]>max) max=a[j];
        }
        if (max==0) printf("die
    ");
            else printf("%.2f
    ",max/2.);
    }
     
    int main(){
        scanf("%lld",&n);
        long i,j,tm,s1=0,s2;
        for (i=1;i<=n;i++)
            scanf("%lld%lld",&vertex[i].x,&vertex[i].y);
        //求总面积
        for (i=2;i<n;i++)
            s1+=area(vertex[1],vertex[i],vertex[i+1]);
        scanf("%lld",&tm);
        for (i=1;i<=tm;i++){
            scanf("%lld%lld",&insd[0].x,&insd[0].y);
            s2=0;
            for (j=1;j<=n;j++)
                s2+=area(insd[0],vertex[j],vertex[j%n+1]);
            //利用面积判断点是否在多边形内部
            if (s1==s2) insd[++m]=insd[0];
        }
        prepare();
        dp();
        return 0;
    }
    

    T2 不老的传说

    题意


    类似于涂色问题,环形问题不多说,断环加倍即可,限制条件if判断就行。终于ac了一道题。。

    解析


    代码

    #include<bits/stdc++.h>
    using namespace std;
    int n,c,p,a[410];
    int f[410][410],ans=1<<30;
    int main(){
    	scanf("%d %d %d",&n,&c,&p);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&a[i]);
    		a[i+n]=a[i];
    	}
    	memset(f,0x3f,sizeof(f));
    	for(int i=1;i<=n;++i){
    		f[i][i]=f[i+n][i+n]=1;
    	}
    	for(int l=2;l<=n;++l){
    		for(int i=1;i<=2*n-l+1;++i){
    			int j=i+l-1;
    			if(a[i]==a[j]&&l<=p) f[i][j]=min(f[i+1][j],f[i][j-1]);
    			else {
    				for(int k=i;k<j;++k){
    					f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
    				}
    			}
    		}
    	}
    	for(int i=1;i<=n;++i){
    		if(f[i][i+n-1]){
    			ans=min(ans,f[i][i+n-1]);
    		}
    	}
    	printf("%d",ans);
    	return 0;
    }
    /*
    5 2 3
    1 2 1 2 1
    */
    

    T3 数字游戏

    题意

    话说考场dfs骗了30分,一开始想的距离正解差一点啊,贪心加dp就可以过的水题,真正太蒻了

    解析

    代码

    #include<bits/stdc++.h>
    using namespace std;
    struct node{
    	int x;
    	int y;
    }a[210];
    int m,n,k;
    int f[210][210];
    bool book[210];
    long long ans;
    bool cmp(node a,node b){
    	return a.y>b.y;
    }
    int main(){
    	scanf("%d %d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&a[i].x);
    	}
    	for(int i=1;i<=n;++i){
    		scanf("%d",&a[i].y);
    	}
    	sort(a+1,a+1+n,cmp);
    	f[0][0]=0;
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=m;++j){
    			f[i][j]=max(f[i-1][j],f[i-1][j-1]+a[i].x-a[i].y*(j-1));
    		}
    	}
    	printf("%lld",f[n][m]);
    	return 0;
    }
    

    T4 多米诺骨牌问题

    题意

    类似于就是背包,考场竟然没想到,打了个爆搜骗了25。

    解析

    代码

    跟解析有点不一样v[i]价值,w[i]重量,s背包容积,背包转移即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e4+5; 
    int n,s,x,y,tot,ans;
    int v[maxn],w[maxn],dp[maxn];
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%d %d",&x,&y);
    		if(x>y){
    			s+=x-y;
    			v[i]=2*(x-y);
    			w[i]=1;
    		}
    		else{
    			s+=y-x;
    			v[i]=2*(y-x);
    			w[i]=-1;
    			tot++;
    		}
    	}
    	for(int i=1;i<=s;++i) dp[i]=maxn;
    	dp[0]=0;
    	for(int i=1;i<=n;++i){
    		for(int j=s;j>=v[i];--j){
    			if(dp[j-v[i]]!=maxn){
    				dp[j]=min(dp[j],dp[j-v[i]]+w[i]);
    			}
    		}
    	}
    	for(int i=s;i>=0;--i){
    		if(dp[i]!=maxn){
    			ans=dp[i];
    			break;
    		}
    	}
    	printf("%d",ans+tot);
    	return 0;
    }
    /*
    4
    6 1
    1 5
    1 3
    1 2
    */
    

    T5 下楼问题

    题意


    大概就是每一楼有3个门问走到第一楼的最长时间

    一道比较简单的dp题,考场看到是英文题便放弃了

    代码(以后再说吧)

    T6 瞬移

    题意


    同上

    解析


    代码(std)

    #include <stdio.h>
    #include <stdlib.h>
    #include <map>
    
    const int maxn = 1000;
    const int maxm = 12;
    
    typedef std::map<std::pair<int, int>, int>::iterator Iter;
    std::map<std::pair<int, int>, int> ans[maxn];
    int tc, tt, n, m, ma, mi, x, y, bans;
    char a[maxn][maxm];
    
    int main ()
    {
    	freopen("teleportation.in", "r", stdin);
    	freopen("teleportation.out", "w", stdout);
      scanf ("%d", &tc);
      for (int tt = 0; tt < tc; tt++)
      {
        scanf ("%d%d%d%d%d%d", &n, &m, &mi, &ma, &x, &y);
        for (int i = 0; i < n; i++)
        {
          scanf ("%s", a[i]);
          // printf ("%s
    ", a[i]);
        }
        ans[0].clear ();
        std::pair<int, int> p = std::make_pair<int, int> (x, y);
        ans[0][p] = 0;
        for (int i = 1; i < n; i++)
        {
          ans[i].clear ();
          for (int j = 0; j < m; j++)
          {
            if (a[i][j] == '*')
            {
              for (int k = j + mi; k <= j + ma && k < m; k++)
              {
                //printf ("--%d: [%d, %d]
    ", i, j, k);
                if (a[i][k] == '*')
                {
                  p = std::make_pair<int, int> (j, k);
                  for (Iter it = ans[i - 1].begin (); it != ans[i - 1].end (); ++it)
                  {
                    int c = it->second + abs (it->first.first - j) + abs (it->first.second - k);
                    if (ans[i].find (p) == ans[i].end () || ans[i][p] > c)
                      ans[i][p] = c;
                  }
                  // printf ("%d: [%d, %d]:%d
    ", i, j, k, ans[i][p]);
                }
              }
            }
          }
        }
        bans = -1;
        for (Iter it = ans[n - 1].begin (); it != ans[n - 1].end (); ++it)
        {
          if (bans == -1 || it->second < bans)
          {
            // printf ("[%d, %d]:%d
    ", it->first.first, it->first.second, it->second);
            bans = it->second;
          }
        }
        printf ("%d
    ", bans);
      }
      return bans >= 0;
    }
    

    T7 护士工作安排问题

    题意


    一道比较好想不好写的题目

    解析

    代码(std)

    #include<stdio.h>
    #include<string.h>
    
    const int N = 20;
    const int DAY = 5;
    const int PAT = 1 << DAY;
    
    int n;
    int love[N][PAT];
    int req[DAY];
    int memo[N][N/2+1][N/2+1][N/2+1][N/2+1][N/2+1];
    int bit[PAT][DAY];
    int changed[DAY];
    
    void preprocess() {
      for (int i = 0; i < PAT; i++) {
        int k = i;
        for (int j = 0; j < DAY; j++) {
          bit[i][DAY - 1 - j] = k & 1;
          k >>= 1;
        }
      }
    }
    inline int getDec(int r0, int r1, int r2, int r3, int r4) {
      return (((((((r0 << 1) | r1) << 1) | r2) << 1) | r3) << 1) | r4;
    }
    void input() {
      scanf("%d", &n);
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < PAT; j++) {
          scanf("%d", &love[i][j]);
        }
      }
      for (int i = 0; i < DAY; i++) {
        scanf("%d", &req[i]);
      }
    }
    int dp(int p, int r0, int r1, int r2, int r3, int r4) {
      if (memo[p][r0][r1][r2][r3][r4] != -1) return memo[p][r0][r1][r2][r3][r4];
      if (p == 0) {
        return memo[p][r0][r1][r2][r3][r4] = love[0][getDec(changed[0] ^ r0,
            changed[1] ^ r1, changed[2] ^ r2, changed[3] ^ r3, changed[4] ^ r4)];
      }
      int ret = 0;
      for (int i = 0; i < PAT; i++) {
        int rr0 = r0 - (bit[i][0] ^ changed[0]);
        int rr1 = r1 - (bit[i][1] ^ changed[1]);
        int rr2 = r2 - (bit[i][2] ^ changed[2]);
        int rr3 = r3 - (bit[i][3] ^ changed[3]);
        int rr4 = r4 - (bit[i][4] ^ changed[4]);
        if (rr0 >= 0 && rr0 <= p && rr1 >= 0 && rr1 <= p
            && rr2 >= 0 && rr2 <= p && rr3 >= 0 && rr3 <= p
            && rr4 >= 0 && rr4 <= p) {
          int t = dp(p - 1, rr0, rr1, rr2, rr3, rr4) + love[p][i];
          if (t > ret) ret = t;
        }
      }
      return memo[p][r0][r1][r2][r3][r4] = ret;
    }
    void solve() {
      for (int i = 0; i < DAY; i++) {
        if (req[i] + req[i] > n) {
          req[i] = n - req[i];
          changed[i] = 1;
        } else {
          changed[i] = 0;
        }
      }
      memset(memo, -1, sizeof(memo));
      printf("%d
    ", dp(n - 1, req[0], req[1], req[2], req[3], req[4]));
    }
    int main() {
      freopen("nurse.in", "r", stdin);
      freopen("nurse.out", "w", stdout);
      preprocess();
      int T;
      scanf("%d", &T);
      while (T--) {
        input();
        solve();
      }
      //while (1);
      return 0;
    }
    

    T8 循环小数

    题意


    给出循环节求分数表达,一道小学数学问题,考场不会写。。

    解析

    A=b+a(10^m-1)

    B=10(n+m)-10n

    再约分输出A,B即可。

    证明自行百度

    代码()

  • 相关阅读:
    第二章:WebDriver 打开Firefox浏览器 和 Chrome 浏览器
    第一章:在 java 中配置 selenium jar 包的步骤
    第一章:Chrome 43 配置 java + selenium 环境
    第一章:火狐浏览器 : 环境配置: FireFox 版本38 + jdk 7 + selenium 2.53.6 + selenum-version 2.48.2
    抛弃CSDN博客 转移到 博客园来编写博客
    第一章:eclipse 中修改字体大小和编码格式
    2. VirtualBox 虚拟机:安装
    1. 在虚拟机中 添加内容
    第一章:selenium + java 环境安装 —— eclipse 中的使用
    实验二 Java面向对象程序设计
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11414975.html
Copyright © 2011-2022 走看看