1. 程式人生 > >濟南day1下午

濟南day1下午

multiset || tdi clear ont tin struct rmi isdigit

下午

預:60+100+30

實:30+30+30

T1水題(water)

T1寫了二分圖匹配

聽說有70分,寫挫了....

正解:貪心,按長度排序,

對於第一幅牌裏面的,在第二個裏面,找一個長度小於,高度最接近的牌

進行覆蓋。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <set>
using namespace std;
int n;
multiset <int> s;
struct node {int x,y;} a[100005],b[100005]; int cmp(node i,node j) {return i.x<j.x;} int main() { freopen("water.in","r",stdin); freopen("water.out","w",stdout); int T; T=1; while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y);
for(int i=0;i<n;i++) scanf("%d%d",&b[i].x,&b[i].y); sort(a,a+n,cmp); sort(b,b+n,cmp); s.clear(); int k=0,ans=0; for(int i=0;i<n;i++) { while(a[i].x>=b[k].x&&k<n) { s.insert(b[k].y); k
++; } if(s.empty())continue; multiset<int>::iterator it=s.upper_bound(a[i].y); if (it==s.begin()) continue; it--; ans++; s.erase(it); } printf("%d\n",ans); } return 0; }

T2下午夢境(dream)

手推公式,推錯了.....30

正解dp||爆搜

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int n,sum,ans,dp[1005][1005],DP[1005][1005],i,j,k,l;
int main()
{
    freopen("dream.in","r",stdin);
    freopen("dream.out","w",stdout);
    scanf("%d",&n);
    sum=int(log(n)/log(2)+0.000000001)+1;
    dp[1][1]=1;
    for (i=1; i<sum; i++)
    {
        for (j=1; j<=n; j++)
          for (k=1; k<=n; k++)
            if (dp[j][k])
              for (l=k+1; l<=j+1; l++)
                DP[min(n,j+l)][l]+=dp[j][k];
        for (j=1; j<=n; j++) for (k=1; k<=n; k++) {dp[j][k]=DP[j][k];DP[j][k]=0;}
    }
    for (j=1; j<=n; j++) ans+=dp[n][j];
    cout<<sum<< <<ans;
    return 0;
}

T3動態規劃(dp)

不會做30分爆搜

正解:

dp[i][j] 1~i 切了j刀,的最優解

dp[i][j]=min{dp[k][j-1]+sum(k+1,i)}

可以證明這個轉移方程具有單調性,zhw說自己yy

20*n^2的簡單dp -> 在固定j的情況下 隨著i的增大,k不降 ,那麽就可分治了

#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 1000011
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))
using namespace std;
int n, q, ans;
int f[N];

struct node
{
    int x, y, z;
}p[N], t[N];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    for(; !isdigit(ch); ch = getchar()) if(ch == -) f = -1;
    for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - 0;
    return x * f;
}

inline bool cmp(node x, node y)
{
    return x.z > y.z;
}

inline int find(int x)
{
    return x == f[x] ? x : f[x] = find(f[x]);
}

inline bool check(int k)
{
    int i, j, x, y, lmin, lmax, rmin, rmax;
    for(i = 1; i <= n + 1; i++) f[i] = i;
    for(i = 1; i <= k; i++) t[i] = p[i];
    std::sort(t + 1, t + k + 1, cmp);
    lmin = lmax = t[1].x;
    rmin = rmax = t[1].y;
    for(i = 2; i <= k; i++)
    {
        if(t[i].z < t[i - 1].z)
        {
            if(find(lmax) > rmin) return 1;
            for(j = find(lmin); j <= rmax; j++)
                f[find(j)] = find(rmax + 1);
            lmin = lmax = t[i].x;
            rmin = rmax = t[i].y;
        }
        else
        {
            lmin = min(lmin, t[i].x);
            lmax = max(lmax, t[i].x);
            rmin = min(rmin, t[i].y);
            rmax = max(rmax, t[i].y);
            if(lmax > rmin) return 1;
        }
    }
//    cout<<find(1)<<endl;
    if(find(lmax) > rmin) return 1;
    return 0;
}

int main()
{
    freopen("number.in","r",stdin);
    freopen("number.out","w",stdout);
    int i, x, y, mid;
    n = read();
    q = read();
    for(i = 1; i <= q; i++)
        p[i].x = read(), p[i].y = read(), p[i].z = read();
    x = 1, y = q;
    //cout<<check(2)<<endl;
    //return 0;
    ans = q + 1;
    while(x <= y)
    {
        mid = (x + y) >> 1;
        if(check(mid)) ans = mid, y = mid - 1;
        else x = mid + 1;
    }
    printf("%d\n", ans);
    return 0;
}

濟南day1下午