[TLE]10123UVa不要歪——其他博客的解法


#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <vector>
using namespace std;

int L, W, N, M;
vector< pair<int, int> > LEFT, RIGHT, D;
//int find_flag; 
pair<int, int> path[128], pick[128];
int check(int n) {
    double LL, LR, RL, RR;
    LL = LR = RL = RR = 0;
    LL = RR = (L/2.0 - 1.5) * (L/2.0 - 1.5) * W / (double)L / 2;
    LR = RL = (L/2.0 + 1.5) * (L/2.0 + 1.5) * W / (double)L / 2;
    for(int i = 0; i < M; i++) {
        if(pick[i].first < -1.5) {
            LL += fabs(pick[i].first - (-1.5)) * pick[i].second;
        } else {
            LR += fabs(pick[i].first - (-1.5)) * pick[i].second;
        }
        if(pick[i].first < 1.5) {
            RL += fabs(pick[i].first - (1.5)) * pick[i].second;
        } else {
            RR += fabs(pick[i].first - (1.5)) * pick[i].second;
        }
    }
    for(int i = 0; i <= n; i++) {
        if(path[i].first < -1.5) {
            LL += fabs(path[i].first - (-1.5)) * path[i].second;
        } else {
            LR += fabs(path[i].first - (-1.5)) * path[i].second;
        }
        if(path[i].first < 1.5) {
            RL += fabs(path[i].first - (1.5)) * path[i].second;
        } else {
            RR += fabs(path[i].first - (1.5)) * path[i].second;
        }
    }
    return LL <= LR && RR <= RL;
}
bool dfs(int l, int r, int dep) {
    if(l == LEFT.size() && r == RIGHT.size()) {
        //find_flag = 1;
        for(int i = dep-1; i >= 0; i--)
            printf("%d %d\n", path[i].first, path[i].second);		
        for(int i = 0; i < M; i++)
            printf("%d %d\n", pick[i].first, pick[i].second);
        return true;
    }
	bool res = false;
    if(l < LEFT.size()) {
        path[dep] = D[LEFT[l].second];
        if(check(dep))
            res = dfs(l+1, r, dep+1);
        if(res)	return true;
    }
    if(r < RIGHT.size()) {
        path[dep] = D[RIGHT[r].second];
        if(check(dep))
            res = dfs(l, r+1, dep+1);
        if(res)	return true;
    }

	return res;
}
int main() {
	//
	freopen("input.txt", "r", stdin);
    int cases = 0, p, q;
    while(scanf("%d %d %d", &L, &W, &N) == 3 && L + W + N) {
        LEFT.clear(), RIGHT.clear(), D.clear();
        M = 0;
        for(int i = 0; i < N; i++) {
            scanf("%d %d", &p, &q);
            D.push_back(make_pair(p, q));
            if(abs(p) < 1.5) {
                pick[M++] = make_pair(p, q);
                continue;
            }
            if(p < 0) {
                LEFT.push_back(make_pair((abs(2*p) - 3) * q, i));
            } else {
                RIGHT.push_back(make_pair((abs(2*p) - 3) * q, i));
            }
        }
        sort(LEFT.begin(), LEFT.end());
        sort(RIGHT.begin(), RIGHT.end());
        //find_flag = 0;
        printf("Case %d:\n", ++cases);
        //dfs(0, 0, 0);
        if(!dfs(0, 0, 0))
            puts("Impossible");
    }	
    return 0;
}

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define N 30

struct block{
    int x;
    int w;
}b[3][N], rec[N];

int L, M, n, cnt[3], vis[3][N];
int ok, pace[3];
double wr1, wr2, wl1, wl2;

bool cmp(const block &a, const block &b){
    return abs(a.x * a.w) < abs(b.x * b.w);
}

void DFS(int cur,int dir, int bo){
    if (cur >= n){
	ok = 1; 
	return;
    }
    int yes = 0;
    for (int i = pace[dir]; i < cnt[dir]; i++){
	if(dir == 0){
//		printf("L%.3lf %.3lf\n", wr2, wl2 + (-3 - b[dir][i].x) * b[dir][i].w);
	    if(wr2 < (wl2 + (-3 - b[dir][i].x) * b[dir][i].w)){
		pace[dir] = i;
		break;
	    }
	    wl1 = wl1 + (3 - b[dir][i].x) * b[dir][i].w;
	    wl2 = wl2 + (-3 - b[dir][i].x) * b[dir][i].w;
	}
	else{
//		printf("R%.3lf %.3lf\n", wr1 + (b[dir][i].x - 3) * b[dir][i].w, wl1);
	    if((wr1 + (b[dir][i].x - 3) * b[dir][i].w) > wl1){
		pace[dir] = i;
		break;
	    }
	    wr1 = wr1 + (b[dir][i].x - 3) * b[dir][i].w;
	    wr2 = wr2 + (b[dir][i].x + 3) * b[dir][i].w;
	}
	yes = 1;
	pace[dir] = i + 1;
	rec[cur++] = b[dir][i];
    }

    if (!bo && !yes){
	ok = -1;
	return;
    }
    DFS(cur, 2 - dir, yes);
    if (ok)	return ;
}

int main(){
    int t = 1;
    while (scanf("%d%d%d", &L, &M, &n), L + M + n){
	// Init;
	memset(b, 0, sizeof(b));
	memset(cnt, 0, sizeof(cnt));
	memset(rec, 0, sizeof(rec));
	memset(pace, 0, sizeof(pace));
	wr1 = wl2 = (L - 3) * (L - 3) * M / (4.0 * L);
	wl1 = wr2 = (L + 3) * (L + 3) * M / (4.0 * L);
	ok = 0;

	// Read;
	int xi, wi;
	for (int i = 0; i < n; i++){
	    scanf("%d%d", &xi, &wi);
	    xi *= 2;
	    if (xi > 3){
		b[2][cnt[2]].x = xi;
		b[2][cnt[2]].w = wi;
		cnt[2]++;
	    }
	    else if (xi < -3){
		b[0][cnt[0]].x = xi;
		b[0][cnt[0]].w = wi;
		cnt[0]++;
	    }
	    else{
		b[1][cnt[1]].x = xi;
		b[1][cnt[1]].w = wi;
		cnt[1]++;
	    }
	}

	// Handle;
	for (int i = 0; i < 3; i++)
	    sort(b[i], b[i] + cnt[i], cmp);
	memcpy(rec, b[1], sizeof(b[1]));
	for (int i = 0; i < cnt[1]; i++){
	    wl1 += (3 - b[1][i].x) * b[1][i].w;
	    wr2 += (b[1][i].x + 3) * b[1][i].w;
	}

	DFS(cnt[1], 0, 1);

	printf("Case %d:\n", t++);
	if(ok == 1){
	    for (int i = n - 1; i >= 0; i--)
		printf("%d %d\n", rec[i].x / 2, rec[i].w);
	}
	else
	    printf("Impossible\n");
    }
    return 0;}

stagginger的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 30;

int N,L,M,N1,N2;
int vis[MAXN],x[MAXN],w[MAXN],s[MAXN],r1[MAXN],r2[MAXN];

int cmp(const void *_a,const void *_b)
{
    int a = *(int *)_a;
    int b = *(int *)_b;
    int x1,x2;
    if (x[a] < 0)
        x1 = (-3-x[a]) * w[a];
    else x1 = (x[a] - 3) * w[a];
    if (x[b] < 0)
        x2 = (-3-x[b]) * w[b];
    else x2 = (x[b]-3) * w[b];
    return x1 - x2 ;
}

void init()
{
    for (int i = 0 ; i < N ; i++)
    {
        scanf("%d%d",&x[i],&w[i]);
        x[i] *= 2;
    }
}

int dfs(int left,int right,int num)
{
    int k,flag,mleft,mright,tleft=1,tright=1;

    if (num == N)
        return 2;

    for (int i = 0 ; i < N1 ; i++)
    {
        k = r1[i];
        if ( !vis[k] )
        {
            vis[k] = 1 ;
            mleft = left + (3+x[k])*w[k];
            mright = right + (3-x[k])*w[k];
            s[num] = k ;
            if (mleft >= 0)      
                tleft =  0 ;

						//将下层的摆放方法传递到这层供剪枝
            if (mleft >= 0 && mright >= 0)
            {
                flag = dfs(mleft,mright,num+1);
                if (flag == 2)      
                    return 2;
                if (flag == -1) //如果再往下放都不成立的话,就别再放左边了
                    break;
            }
            vis[k] = 0 ;
        }
    }

    for (int i = 0 ; i < N2 ; i++)
    {
        k = r2[i];
        if ( !vis[k] )
        { 
            vis[k] = 1 ;
            mleft = left + (3+x[k]) * w[k];
            mright = right + (3-x[k]) * w[k];
            s[num] = k ;
            if (mright >= 0)
                tright = 0;

            if ( mleft >=0 && mright >= 0)
            {
                flag = dfs(mleft,mright,num+1);
                if (flag == 2)
                    return 2 ;
                if (flag == 1 )  // 再放下放都不成立的话,就不再放右边了
                    break;
            }
            vis[k] = 0 ;
        }
    }
    return tright - tleft ;     // 判断并返还这两次放的是否成立,返还零的话,就让它回溯,尝试别的方法
}

void solve()
{
    int left,right,num=0;
    memset(vis,0,sizeof(vis));
    left = right = 3 * M;

    for (int i = 0 ; i < N ; i++)
        if ( x[i] >= -3 && x[i] <= 3)
        {
            s[num++] = i;
            vis[i] = 1 ;
            left += (3 + x[i]) * w[i];
            right +=(3 - x[i]) * w[i];
        }

    N1 = N2 = 0 ;
    for (int i = 0 ; i < N ; i++)
    {
        if ( !vis[i] )
        {
            if ( x[i] < 0)
                r1[N1++] = i ;
            else r2[N2++] = i ;
        }
    }
    
    qsort(r1,N1,sizeof(r1[0]),cmp);
    qsort(r2,N2,sizeof(r2[0]),cmp);

    if ( dfs(left,right,num) != 2 )
        printf("Impossible\n");
    else 
        for (int  i = N-1 ; i >= 0 ; i--)
            printf("%d %d\n",x[s[i]]/2,w[s[i]]);
}

int main()
{
    int t = 0;
    while (scanf("%d%d%d",&L,&M,&N) != EOF )
    {
        if (!L)
            break;
        init();
        printf("Case %d:\n",++t);
        solve();
    }
    return 0;
}


#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;

const int N = 20 + 5;
struct wood {
	int pos;
	int weight;
	int torque;
}leftw[N],rightw[N],res[N];
bool ok ;
int num,l,wei;
int leftnum ,rightnum,left,right,midnum;

int cmp (wood a ,wood b) {
	return a.torque < b.torque;
}
bool yes(int l ,int r) {
	int suml = 0;
	int sumr = 0;
	for (int i = 0 ; i < l ;i++) {
		suml += (-leftw[i].pos * 2 - 3) * leftw[i].weight;
	}
	for (int i = 0 ; i < r ;i++) {
		sumr += (rightw[i].pos * 2 + 3) * rightw[i].weight;	
	}
	sumr += wei;
	if (suml > sumr)
		return false;
	suml = 0;
   	sumr = 0;
	for (int i = 0; i < l; i++) {
		suml += (-leftw[i].pos * 2 + 3) * leftw[i].weight;
	}
	for (int i = 0; i < r; i++) {
		sumr += (rightw[i].pos * 2 - 3) * rightw[i].weight;
	}
	suml += wei;
	if (sumr > suml)
	   	return false;
	return true;;

}
void dfs (int cur ,int l ,int r) {
	if (cur == num) {
		if(yes(l,r))//check whether the final state is balanced(i add this myself)
		{
			for (int i = cur - 1 ; i >= 0 ;i--) {
				cout <<res[i].pos <<" "<<res[i].weight<<endl;
			}
			ok = true;
		}
		return;
	}
	for (int i = l ; i < leftnum ;i++) {
		if(yes(i,r) && !ok) {
			//i is being inserted while r is not, so <= in function 'yes' does not work
			res[cur].pos = leftw[i].pos;
			res[cur].weight = leftw[i].weight;
			dfs(cur + 1, i + 1,r);
		}
		else
			break;
	}
	for (int i = r ; i < rightnum ;i++) {
		if(yes(l,i) && !ok) {
			res[cur].pos = rightw[i].pos;
			res[cur].weight = rightw[i].weight;
			dfs(cur + 1, l, i + 1);
		}
		else
			break;
	}
}
int main () {
	//
	freopen("input.txt", "r", stdin);

	int a,b;
	int T = 1;
	while (cin >> l >> wei >> num && l + wei +num) {
		leftnum = rightnum = 0 ;
		for (int i = 0 ; i < num ; i++) {
			cin >> a >> b;
			if (a >= 0) {
				rightw[rightnum].pos = a;
				rightw[rightnum].weight = b;
				rightw[rightnum++].torque = (a * 2 - 3) * b;
			}
			if (a < 0) {
				leftw[leftnum].pos = a;
				leftw[leftnum].weight = b;
				leftw[leftnum++].torque = (-a * 2 - 3) * b;			
			}

		}
		sort(leftw ,leftw + leftnum ,cmp);
		sort(rightw , rightw + rightnum ,cmp);
		wei = wei * 3;
		ok = false;
		cout << "Case "<< T++ << ":\n";
		dfs(0,0,0);
		if(!ok)
			cout << "Impossible" <<endl; 
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值