1. 程式人生 > >CSU 1116: Kingdoms 1117: 網格中的三角形 1119: Collecting Coins

CSU 1116: Kingdoms 1117: 網格中的三角形 1119: Collecting Coins


#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
#define INF 0x3f3f3f3f

int map[20][20],people[20],low[20];
int n,m,p;
int vis[20];

int prim(int t,int& sum)
{ memset(vis,0,sizeof(vis)); int pos,price,tot; pos=1; price=0; tot=0; for(int i=1;i<=n;i++)//尋找每種情況包含的點 { vis[i]=t&1; t=(t>>1); if(vis[i]) tot++;//記錄有多少點 } if(vis[1]==0) tot++; for(int i=1;i<=n;i++) { if(vis[i]) low[i]=map
[pos][i]; else low[i]=INF; } low[1]=0; vis[1]=2; tot--;//只需要將tot個點進行最小生成樹就行了 int MIN; for(int k=1;k<=tot;k++) { MIN=INF; pos=1; for(int i=1;i<=n;i++) { if(vis[i]==1&&MIN>low[i]) { MIN=low[i]; pos=i; } } if
(pos==1) return INF;//如果存在點擴充套件不到,就果斷放棄這種情況 price+=low[pos]; sum+=people[pos]; vis[pos]=2; for(int i=1;i<=n;i++) { if(vis[i]==1&&map[pos][i]<low[i]) low[i]=map[pos][i]; } } return price; } int main() { // freopen("s","r",stdin); int T; scanf("%d",&T); while(T--) { memset(map,0x3f,sizeof(map)); scanf("%d%d%d",&n,&m,&p); for(int i=1;i<=n;i++) scanf("%d",&people[i]);//記錄每個城市的人數 for(int j=1;j<=m;j++) { int u,v,c; scanf("%d%d%d",&u,&v,&c); if(c<map[u][v])//處理重邊,保留花費最少的邊 { map[u][v]=map[v][u]=c; } } int price,sum,res=0; // cout<<(1<<(n-1))<<endl; for(int i=0;i<=(1<<(n));i++)//列舉點,對每個情況找一次最小生成樹 { sum=people[1]; price=prim(i,sum);//返回總花費 if(price<=p) res=max(res,sum);//更新最大的人數 } printf("%d\n",res); } return 0; } /********************************************************************** Problem: 1116 User: 3901140225 Language: C++ Result: AC Time:232 ms Memory:2024 kb **********************************************************************/

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long ll;

inline ll max(ll a, ll b) {
    return a > b ? a : b;
}

inline ll min(ll a, ll b) {
    return a < b ? a : b;
}

ll N, M, A, B;

ll solve (ll k) {
    if (k < 0)
        k = 0;

    if (N > M)
        swap(N, M);

    ll ans = 0;
    for (ll n = 1; n <= N; n++) {
        for (ll m = 1; m <= M; m++) {
            ll cnt = 0;

            if (n * m <= k)
                cnt += 2 * (n + m - 2);

            ll l, r;
            for (ll x = 0; x <= n; x ++) {
                r = (m * x + k) / n;

                if (r > m)
                    r = m;

                ll t = m * x - k;

                if(t <= 0) 
                    l = 0;
                else 
                    l = (t - 1) / n + 1;

                if(l <= r) 
                    cnt += 2 * (r - l + 1);
            }

            for (ll x = 1; x < n; x++) {
                ll tmp = n * m - x;

                if (tmp <= k)
                    cnt += 4 * (m - 1);
                else {
                    tmp = tmp - k;
                    ll u = m-1 - min(tmp / x + (tmp % x != 0), m-1);
                    cnt += 4 * u;
                }
            }
            //printf("%lld %lld %lld\n",n , m,  cnt);
            ans += cnt * (N - n + 1) * (M - m + 1);
        }
    }
    return ans;
}

int main () {
    int cas;
    scanf("%d", &cas);
    while (cas--) {
        scanf("%lld%lld%lld%lld", &N, &M, &A, &B);
        printf("%lld\n", solve(B*2) - solve(A*2-1));
    }
    return 0;
}
/**********************************************************************
	Problem: 1117
	User: 3901140225
	Language: C++
	Result: AC
	Time:2364 ms
	Memory:1120 kb
**********************************************************************/

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct node{
   int x,y,flag;
};
node st[6];
node ccc[11];
int n,m;
int vis[30][30];
char map[30][30];
int zx,zy;
int cnt;
int res,ans,ans1;
int c,co;
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int jude(int x,int y)
{
    if(x<1||x>n||y<1||y>m) return 0;
    return 1;
}
void dfs(int x,int y)
{
    if(map[x][y]=='C') res++,map[x][y]='.';
    vis[x][y]=1;
    for(int i=0;i<4;i++)
    {   int xx=x+dir[i][0];
        int yy=y+dir[i][1];
        if(!jude(xx,yy)||vis[xx][yy]||map[xx][yy]=='O'||map[xx][yy]=='X') continue;
        dfs(xx,yy);
    }
}
void dfs4(int x,int y,node *df,int &co)//推完一個石頭能吃到的金幣個數
{
    if(map[x][y]=='C') res++,map[x][y]='.',df[co].x=x,df[co++].y=y;//記錄金幣的位置,後面回溯。
    vis[x][y]=1;
    for(int i=0;i<4;i++)
    {   int xx=x+dir[i][0];
        int yy=y+dir[i][1];
        if(!jude(xx,yy)||vis[xx][yy]||map[xx][yy]=='O'||map[xx][yy]=='X') continue;
        dfs4(xx,yy,df,co);

    }
}
int dfs1(int x,int y,int zx,int zy)//判斷是否能到達推石頭的那個點。
{
    vis[x][y]=1;
    if(x==zx&&y==zy) return 1;
    for(int i=0;i<4;i++)
    {   int xx=x+dir[i][0];
        int yy=y+dir[i][1];
        if(!jude(xx,yy)||vis[xx][yy]||map[xx][yy]=='X'||map[xx][yy]=='O') continue;
        if(dfs1(xx,yy,zx,zy)) return 1;
    }
    return 0;
}
void solove(int num,int sum)//第幾個石頭,金幣和
{
    if(num==cnt-1)//最後一個石頭推完
        {
            if(ans1<sum) ans1=sum;
            return ;
        }
    if(ans+ans1==c) return ;
    for(int i=1;i<cnt&&ans+ans1<c;i++)//暴力列舉石頭
    {
        if(!st[i].flag) continue ;
        st[i].flag=0;
        for(int j=0;j<4;j++)//列舉方向
        {
            int xx=st[i].x+dir[j][0];//根據你的位置得到的石頭的前後位置。
            int yy=st[i].y+dir[j][1];
            int x2=st[i].x-dir[j][0];
            int y2=st[i].y-dir[j][1];
            if(!jude(xx,yy)||map[xx][yy]=='C'||map[xx][yy]=='O'||map[xx][yy]=='X') continue;//當石頭後面不為空或者出界
            if(!jude(x2,y2)||map[x2][y2]=='O'||map[x2][y2]=='X') continue;//當人站的那個位置還有石頭或者為障礙
            memset(vis,0,sizeof(vis));
            if(!dfs1(zx,zy,x2,y2)) continue;//當人不能到達推石頭的那個位置
            map[st[i].x][st[i].y]='.';//能推就把石頭那個位置變成路
            map[xx][yy]='X';//石頭後面的位置變成障礙
            memset(vis,0,sizeof(vis));
            int co=0;
            node *df=(node*)malloc(sizeof(node)*10);//最多是個金幣,用來儲存這一輪完石頭所吃的金幣位置用於後面的回溯
             res=0;
            dfs4(zx,zy,df,co);//推完這次石頭然後去吃硬幣
            solove(num+1,sum+res);//繼續往下面列舉石頭
             for(int k=0;k<co;k++)//回溯地圖上的金幣
            {
               map[df[k].x][df[k].y]='C';
            }
            map[st[i].x][st[i].y]='O';//回溯石頭的位置
            map[xx][yy]='.';

        }
        st[i].flag=1;
        if(ans1<sum) ans1=sum;//取最大
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        cnt=1;
        c=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",map[i]+1);
            for(int j=1;j<=m;j++)
            {
                if(map[i][j]=='S')
                {
                    zx=i;
                    zy=j;
                    map[i][j]='.';

                }
                if (map[i][j] == 'C') c++;
                if(map[i][j]=='O')
                {
                    st[cnt].x=i,st[cnt].y=j;
                    st[cnt++].flag=1;
                }
            }
        }
        res=0;
        memset(vis,0,sizeof(vis));
        dfs(zx,zy);//不推石頭直接能吃的金幣個數
        ans=res;
        ans1=0;
        solove(0,0);
        printf("%d\n",ans+ans1);
    }
}

/**********************************************************************
	Problem: 1119
	User: 3901140225
	Language: C++
	Result: AC
	Time:48 ms
	Memory:1652 kb
**********************************************************************/