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即可。

    证明自行百度

    代码()

  • 相关阅读:
    ubuntu 制做samba
    《Programming WPF》翻译 第4章 前言
    《Programming WPF》翻译 第4章 3.绑定到数据列表
    《Programming WPF》翻译 第4章 4.数据源
    《Programming WPF》翻译 第5章 6.触发器
    《Programming WPF》翻译 第4章 2.数据绑定
    《Programming WPF》翻译 第4章 1.不使用数据绑定
    《Programming WPF》翻译 第5章 7.控件模板
    《Programming WPF》翻译 第5章 8.我们进行到哪里了?
    《Programming WPF》翻译 第5章 5.数据模板和样式
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11414975.html
Copyright © 2011-2022 走看看